]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Add state change i/o hook to the core and change some spidermonkey behaviour.
authorAnthony Minessale <anthony.minessale@gmail.com>
Tue, 27 Mar 2007 00:40:53 +0000 (00:40 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Tue, 27 Mar 2007 00:40:53 +0000 (00:40 +0000)
The most important thing to check is you now must create a new session with a blank constructor:
s = new Session();
then call s.originate() with all the former args that were documented to be for the constructor
this will will return true or false to indicate if the call worked.

See below this sample code demonstrates all of the changes:

////////////////////////////////////////////////////////////////////////////////
function on_hangup(hup_session)
{
    console_log("debug", "HANGUP!!!! name: " + hup_session.name + " cause: " + hup_session.cause + "\n");
//exit here would end the script so you could cleanup and just be done
//exit();
}

//set the on_hangup function to be called when this session is hungup
session.setHangupHook(on_hangup);

//allocate a new b_session
var b_session = new Session();

//make a call with b_session.  If this fails, all we will be able to access is the b_session.cause attr
if (b_session.originate(session, "sofia/mydomain.com/888@conference.freeswitch.org")) {
//Inform the scripting engine to automaticly hang this session up when the script ends
    b_session.setAutoHangup(true);
//set the on_hangup function to be called when this session is hungup
    b_session.setHangupHook(on_hangup);
//bridge session with b_session
    bridge(session, b_session);
} else {
    console_log("debug", "Originate Failed.. cause: " + b_session.cause + "\n");
}
////////////////////////////////////////////////////////////////////////////////

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4773 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_core.h
src/include/switch_module_interfaces.h
src/include/switch_types.h
src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
src/mod/languages/mod_spidermonkey/mod_spidermonkey.h
src/switch_core.c

index cb20f64a7ad5e0176cbca390959d9713e56f32a4..b08ff2db1478dac7e4c73fa0f0d97e7af2f6a66d 100644 (file)
@@ -856,6 +856,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_waitfor_write
   \return SWITCH_STATUS_SUCCESS on suceess
 */
 SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_send_dtmf(switch_core_session_t *session, switch_send_dtmf_hook_t send_dtmf);
+
+/*! 
+  \brief Add an event hook to be executed when a session receives a state change signal
+  \param session session to bind hook to
+  \param state_change hook to bind
+  \return SWITCH_STATUS_SUCCESS on suceess
+*/
+SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_state_change(switch_core_session_t *session,
+                                                                                                                                                               switch_answer_channel_hook_t state_change);
 ///\}
 
 ///\defgroup hashf Hash Functions
index 3af505f64cafd7f15ff602be09638f9d393278fa..eb534fbdb5d94bc34fad7de800b7b03dbf0203eb 100644 (file)
@@ -145,6 +145,13 @@ struct switch_io_event_hook_send_dtmf {
        struct switch_io_event_hook_send_dtmf *next;
 };
 
+/*! \brief Node in which to store state change callback hooks */
+struct switch_io_event_hook_state_change {
+       /*! the send dtmf channel callback hook*/
+       switch_state_change_hook_t state_change;
+       struct switch_io_event_hook_state_change *next;
+};
+
 /*! \brief A table of lists of io_event_hooks to store the event hooks associated with a session */
 struct switch_io_event_hooks {
        /*! a list of outgoing channel hooks */
@@ -167,6 +174,8 @@ struct switch_io_event_hooks {
        switch_io_event_hook_waitfor_write_t *waitfor_write;
        /*! a list of send dtmf hooks */
        switch_io_event_hook_send_dtmf_t *send_dtmf;
+       /*! a list of state change hooks */
+       switch_io_event_hook_state_change_t *state_change;
 };
 
 /*! \brief A table of i/o routines that an endpoint interface can implement */
@@ -191,6 +200,8 @@ struct switch_io_routines {
        switch_status_t (*receive_message)(switch_core_session_t *, switch_core_session_message_t *);
        /*! queue a message for another session*/
        switch_status_t (*receive_event)(switch_core_session_t *, switch_event_t *);
+       /*! change a sessions channel state */
+       switch_status_t (*state_change)(switch_core_session_t *);
 };
 
 /*! \brief Abstraction of an module endpoint interface
index b8fb015902c3aa1ef0a4c2a6d1c707a7b4473445..d98417b1e36e1d6a1ded0f5d774236003ed58b5e 100644 (file)
@@ -954,6 +954,7 @@ typedef struct switch_io_event_hook_kill_channel switch_io_event_hook_kill_chann
 typedef struct switch_io_event_hook_waitfor_read switch_io_event_hook_waitfor_read_t;
 typedef struct switch_io_event_hook_waitfor_write switch_io_event_hook_waitfor_write_t;
 typedef struct switch_io_event_hook_send_dtmf switch_io_event_hook_send_dtmf_t;
+typedef struct switch_io_event_hook_state_change switch_io_event_hook_state_change_t;
 typedef struct switch_io_routines switch_io_routines_t;
 typedef struct switch_io_event_hooks switch_io_event_hooks_t;
 typedef struct switch_speech_handle switch_speech_handle_t;
@@ -989,6 +990,7 @@ typedef switch_status_t (*switch_kill_channel_hook_t)(switch_core_session_t *, i
 typedef switch_status_t (*switch_waitfor_read_hook_t)(switch_core_session_t *, int, int);
 typedef switch_status_t (*switch_waitfor_write_hook_t)(switch_core_session_t *, int, int);
 typedef switch_status_t (*switch_send_dtmf_hook_t)(switch_core_session_t *, char *);
+typedef switch_status_t (*switch_state_change_hook_t)(switch_core_session_t *);
 typedef struct switch_stream_handle switch_stream_handle_t;
 typedef switch_status_t (*switch_stream_handle_write_function_t)(switch_stream_handle_t *handle, const char *fmt, ...);
 typedef switch_status_t (*switch_api_function_t)(char *in, switch_core_session_t *session, switch_stream_handle_t *stream);
index 1ecd49bdfc29c81b46051153c2274ef935b1775d..cc0dc62b6f5f0dc8bbf907121e3b8002ffd93a3c 100644 (file)
@@ -43,6 +43,7 @@ static const char modname[] = "mod_spidermonkey";
 
 static void session_destroy(JSContext *cx, JSObject *obj);
 static JSBool session_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+static JSBool session_originate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
 static switch_api_interface_t js_run_interface;
 
 static struct {
@@ -79,7 +80,8 @@ struct sm_loadable_module {
 typedef struct sm_loadable_module sm_loadable_module_t;
 
 typedef enum {
-       S_HUP = (1 << 0)
+       S_HUP = (1 << 0),
+       S_FREE = (1 << 1)
 } session_flag_t;
 
 struct input_callback_state {
@@ -640,7 +642,8 @@ static switch_status_t js_common_callback(switch_core_session_t *session, void *
        jsval argv[4];
        JSObject *Event = NULL;
 
-       if (!jss) {
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
                return SWITCH_STATUS_FALSE;
        }
 
@@ -822,15 +825,15 @@ static JSBool session_flush_digits(JSContext *cx, JSObject *obj, uintN argc, jsv
        switch_size_t has;
        switch_channel_t *channel;
 
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
        channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
-    if (!switch_channel_ready(channel)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session is not active!\n");
-        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-        return JS_TRUE;
-    }
-
        while ((has = switch_channel_has_dtmf(channel))) {
                switch_channel_dequeue_dtmf(channel, buf, sizeof(buf));
        }
@@ -845,14 +848,14 @@ static JSBool session_flush_events(JSContext *cx, JSObject *obj, uintN argc, jsv
        switch_event_t *event;
     switch_channel_t *channel;
 
+       if (!jss || !jss->session) {
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
     channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
-    if (!switch_channel_ready(channel)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session is not active!\n");
-        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-        return JS_TRUE;
-    }
 
        while (switch_core_session_dequeue_event(jss->session, &event) == SWITCH_STATUS_SUCCESS) {
                switch_event_destroy(&event);
@@ -877,6 +880,12 @@ static JSBool session_recordfile(JSContext *cx, JSObject *obj, uintN argc, jsval
     int32 limit = 0;
     switch_input_args_t args = {0};
 
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
        channel = switch_core_session_get_channel(jss->session);
        assert(channel != NULL);
 
@@ -953,6 +962,13 @@ static JSBool session_collect_input(JSContext *cx, JSObject *obj, uintN argc, js
        JSFunction *function;
     switch_input_args_t args = {0};
 
+
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
        channel = switch_core_session_get_channel(jss->session);
        assert(channel != NULL);
 
@@ -1014,6 +1030,12 @@ static JSBool session_sayphrase(JSContext *cx, JSObject *obj, uintN argc, jsval
        JSFunction *function;
     switch_input_args_t args = {0};
 
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
        channel = switch_core_session_get_channel(jss->session);
        assert(channel != NULL);
 
@@ -1074,6 +1096,55 @@ static JSBool session_sayphrase(JSContext *cx, JSObject *obj, uintN argc, jsval
        return JS_TRUE;
 }
 
+static void check_hangup_hook(struct js_session *jss)
+{
+       jsval argv[2] = {0};
+       int argc = 0;
+       jsval ret;
+       if (jss->on_hangup ) {
+               argv[argc++] = OBJECT_TO_JSVAL(jss->obj);                       
+               JS_CallFunction(jss->cx, jss->obj, jss->on_hangup, argc, argv, &ret);
+       }
+}
+
+static switch_status_t hanguphook(switch_core_session_t *session)
+{
+       switch_channel_t *channel;
+       struct js_session *jss = NULL;
+
+       channel = switch_core_session_get_channel(session);
+       assert(channel != NULL);
+       if (switch_channel_get_state(channel) == CS_HANGUP) {
+               if ((jss = switch_channel_get_private(channel, "jss"))) {
+                       check_hangup_hook(jss);
+               }
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+static JSBool session_hanguphook(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       JSFunction *function;
+       struct js_session *jss;
+       *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+
+       if ((jss = JS_GetPrivate(cx, obj)) && jss->session) {
+               if (argc > 0) {
+                       if ((function = JS_ValueToFunction(cx, argv[0]))) {
+                               switch_channel_t *channel = switch_core_session_get_channel(jss->session);
+                               assert(channel != NULL);
+                               jss->on_hangup = function;
+                               switch_channel_set_private(channel, "jss", jss);
+                               switch_core_session_add_event_hook_state_change(jss->session, hanguphook);
+                               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+                       }
+               }
+       }
+
+       return JS_TRUE;
+}
+
 static JSBool session_streamfile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
        struct js_session *jss = JS_GetPrivate(cx, obj);
@@ -1088,6 +1159,12 @@ static JSBool session_streamfile(JSContext *cx, JSObject *obj, uintN argc, jsval
        JSFunction *function;
     switch_input_args_t args = {0};
 
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
        channel = switch_core_session_get_channel(jss->session);
        assert(channel != NULL);
 
@@ -1147,16 +1224,15 @@ static JSBool session_set_variable(JSContext *cx, JSObject *obj, uintN argc, jsv
        struct js_session *jss = JS_GetPrivate(cx, obj);
     switch_channel_t *channel;
 
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
        channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
-    if (!switch_channel_ready(channel)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session is not active!\n");
-        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-        return JS_TRUE;
-    }
-
-
        if (argc > 1) {
                char *var, *val;
 
@@ -1176,16 +1252,14 @@ static JSBool session_get_variable(JSContext *cx, JSObject *obj, uintN argc, jsv
        struct js_session *jss = JS_GetPrivate(cx, obj);
     switch_channel_t *channel;
 
+       if (!jss || !jss->session) {
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
        channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
-    if (!switch_channel_ready(channel)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session is not active!\n");
-        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-        return JS_TRUE;
-    }
-
-
        if (argc > 0) {
                char *var, *val;
                
@@ -1220,6 +1294,12 @@ static JSBool session_speak(JSContext *cx, JSObject *obj, uintN argc, jsval *arg
        JSFunction *function;
     switch_input_args_t args = {0};
 
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
        channel = switch_core_session_get_channel(jss->session);
        assert(channel != NULL);
 
@@ -1286,6 +1366,12 @@ static JSBool session_get_digits(JSContext *cx, JSObject *obj, uintN argc, jsval
        int32 digits = 0, timeout = 5000;
        switch_channel_t *channel;
 
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
        channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
@@ -1321,11 +1407,42 @@ static JSBool session_get_digits(JSContext *cx, JSObject *obj, uintN argc, jsval
        return JS_FALSE;
 }
 
+static JSBool session_autohangup(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       struct js_session *jss = JS_GetPrivate(cx, obj);
+       *rval = BOOLEAN_TO_JSVAL(JS_FALSE);
+
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+       
+       if (argv[0]) {
+               JSBool tf;
+               JS_ValueToBoolean(cx, argv[0], &tf);
+               if (tf == JS_TRUE) {
+                       switch_set_flag(jss, S_HUP);
+               } else {
+                       switch_clear_flag(jss, S_HUP);
+               }
+               *rval = BOOLEAN_TO_JSVAL(tf);
+       }
+
+       return JS_TRUE;
+}
+
 static JSBool session_answer(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
        struct js_session *jss = JS_GetPrivate(cx, obj);
        switch_channel_t *channel;
 
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
        channel = switch_core_session_get_channel(jss->session);
        assert(channel != NULL);
 
@@ -1349,6 +1466,11 @@ static JSBool session_cdr(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        /*Always a pessimist... sheesh!*/
        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
 
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               return JS_TRUE;
+       }
+
     if (switch_ivr_generate_xml_cdr(jss->session, &cdr) == SWITCH_STATUS_SUCCESS) {
                char *xml_text;
                if ((xml_text = switch_xml_toxml(cdr))) {
@@ -1366,6 +1488,12 @@ static JSBool session_ready(JSContext *cx, JSObject *obj, uintN argc, jsval *arg
        struct js_session *jss = JS_GetPrivate(cx, obj);
        switch_channel_t *channel;
 
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
        channel = switch_core_session_get_channel(jss->session);
        assert(channel != NULL);
 
@@ -1384,6 +1512,12 @@ static JSBool session_wait_for_media(JSContext *cx, JSObject *obj, uintN argc, j
        unsigned int elapsed;
        int32 timeout = 60;
 
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
        channel = switch_core_session_get_channel(jss->session);
        assert(channel != NULL);
 
@@ -1419,6 +1553,12 @@ static JSBool session_wait_for_answer(JSContext *cx, JSObject *obj, uintN argc,
        unsigned int elapsed;
        int32 timeout = 60;
 
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
        channel = switch_core_session_get_channel(jss->session);
        assert(channel != NULL);
 
@@ -1451,6 +1591,12 @@ static JSBool session_execute(JSContext *cx, JSObject *obj, uintN argc, jsval *a
        switch_channel_t *channel;
     struct js_session *jss = JS_GetPrivate(cx, obj);
 
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
        channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
@@ -1468,6 +1614,12 @@ static JSBool session_execute(JSContext *cx, JSObject *obj, uintN argc, jsval *a
                struct js_session *jss = JS_GetPrivate(cx, obj);
                jsrefcount saveDepth;
 
+               if (!jss || !jss->session) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+                       *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+                       return JS_TRUE;
+               }
+
                if ((application_interface = switch_loadable_module_get_application_interface(app_name))) {
                        if (application_interface->application_function) {
                                saveDepth = JS_SuspendRequest(cx);
@@ -1486,17 +1638,12 @@ static JSBool session_get_event(JSContext *cx, JSObject *obj, uintN argc, jsval
 {
        struct js_session *jss = JS_GetPrivate(cx, obj);
        switch_event_t *event;
-       switch_channel_t *channel;
-
-       channel = switch_core_session_get_channel(jss->session);
-    assert(channel != NULL);
-
-    if (!switch_channel_ready(channel)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session is not active!\n");
-        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-        return JS_TRUE;
-    }
 
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
 
        if (switch_core_session_dequeue_event(jss->session, &event) == SWITCH_STATUS_SUCCESS) {
                JSObject *Event;
@@ -1528,6 +1675,12 @@ static JSBool session_send_event(JSContext *cx, JSObject *obj, uintN argc, jsval
        JSObject *Event;
        struct event_obj *eo;
 
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
        if (argc > 0) {
                if (JS_ValueToObject(cx, argv[0], &Event)) {
                        if ((eo = JS_GetPrivate(cx, Event))) {
@@ -1554,6 +1707,12 @@ static JSBool session_hangup(JSContext *cx, JSObject *obj, uintN argc, jsval *ar
        char *cause_name = NULL;
        switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
 
+       if (!jss || !jss->session) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
        channel = switch_core_session_get_channel(jss->session);
        assert(channel != NULL);
 
@@ -1722,10 +1881,13 @@ static JSBool js_fetchurl_file(JSContext *cx, JSObject *obj, uintN argc, jsval *
 /*********************************************************************************/
 enum session_tinyid {
        SESSION_NAME, SESSION_STATE,
-       PROFILE_DIALPLAN, PROFILE_CID_NAME, PROFILE_CID_NUM, PROFILE_IP, PROFILE_ANI, PROFILE_ANI_II, PROFILE_DEST, SESSION_UUID
+       PROFILE_DIALPLAN, PROFILE_CID_NAME, PROFILE_CID_NUM, PROFILE_IP, PROFILE_ANI, PROFILE_ANI_II, PROFILE_DEST, SESSION_UUID, SESSION_CAUSE
 };
 
 static JSFunctionSpec session_methods[] = {
+       {"originate", session_originate, 2}, 
+       {"setHangupHook", session_hanguphook, 1}, 
+       {"setAutoHangup", session_autohangup, 1}, 
     {"sayPhrase", session_sayphrase, 1}, 
     {"streamFile", session_streamfile, 1}, 
        {"collectInput", session_collect_input, 1}, 
@@ -1760,6 +1922,7 @@ static JSPropertySpec session_props[] = {
        {"aniii", PROFILE_ANI_II, JSPROP_READONLY|JSPROP_PERMANENT}, 
        {"destination", PROFILE_DEST, JSPROP_READONLY|JSPROP_PERMANENT}, 
        {"uuid", SESSION_UUID, JSPROP_READONLY|JSPROP_PERMANENT}, 
+       {"cause", SESSION_CAUSE, JSPROP_READONLY|JSPROP_PERMANENT}, 
        {0}
 };
 
@@ -1767,29 +1930,40 @@ static JSBool session_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval
 {
        struct js_session *jss = JS_GetPrivate(cx, obj);
        int param = 0;
-       JSBool res = JS_TRUE;
-       switch_channel_t *channel;
-       switch_caller_profile_t *caller_profile;
-       char *name;
-       
-       if (!jss || !jss->session) {
-               return JS_FALSE;
-       }
+       switch_channel_t *channel = NULL;
+       switch_caller_profile_t *caller_profile = NULL;
+       char *name = NULL;
 
-       channel = switch_core_session_get_channel(jss->session);
-       assert(channel != NULL);
-
-       caller_profile = switch_channel_get_caller_profile(channel);
+       if (jss && jss->session) {
+               channel = switch_core_session_get_channel(jss->session);
+               assert(channel != NULL);
+               caller_profile = switch_channel_get_caller_profile(channel);
+       }
 
        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;
        }
-       
+
+       if (!channel) {
+               switch(param) {
+               case SESSION_CAUSE:
+                       *vp = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, switch_channel_cause2str(jss->cause)));
+                       break;
+               default:
+                       *vp = BOOLEAN_TO_JSVAL(JS_FALSE);
+               }
+               return JS_TRUE;
+       }
+
        switch(param) {
+       case SESSION_CAUSE:
+               *vp = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, switch_channel_cause2str(switch_channel_get_cause(channel))));
+               break;
        case SESSION_NAME:
                *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, switch_channel_get_name(channel)));
                break;
@@ -1835,12 +2009,12 @@ static JSBool session_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval
                }
                break;
        default:
-               res = JS_FALSE;
+               *vp = BOOLEAN_TO_JSVAL(JS_FALSE);
                break;
-
+               
        }
 
-       return res;
+       return JS_TRUE;
 }
 
 JSClass session_class = {
@@ -1859,7 +2033,7 @@ static JSObject *new_js_session(JSContext *cx, JSObject *obj, switch_core_sessio
                jss->session = session;
                jss->flags = flags;
                jss->cx = cx;
-               jss->obj = obj;
+               jss->obj = session_obj;
                if ((JS_SetPrivate(cx, session_obj, jss) &&
                         JS_DefineProperties(cx, session_obj, session_props) &&
                         JS_DefineFunctions(cx, session_obj, session_methods))) {
@@ -1870,18 +2044,36 @@ static JSObject *new_js_session(JSContext *cx, JSObject *obj, switch_core_sessio
        return NULL;
 }
 
-
 /* Session Object */
 /*********************************************************************************/
+
 static JSBool session_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
+       struct js_session *jss = NULL;
+
+       assert((jss = malloc(sizeof(*jss))));
+       memset(jss, 0, sizeof(*jss));
+       jss->cx = cx;
+       jss->obj = obj;
+       switch_set_flag(jss, S_FREE);
+
+       JS_SetPrivate(cx, obj, jss);
+
+       return JS_TRUE;
+}
+
+static JSBool session_originate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       struct js_session *jss = NULL;
        switch_memory_pool_t *pool = NULL;
+
+       jss = JS_GetPrivate(cx, obj);
+       jss->cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+
        if (argc > 1) {
-               switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
-               struct js_session *jss = NULL;
                JSObject *session_obj;
                switch_core_session_t *session = NULL, *peer_session = NULL;
-               switch_caller_profile_t *caller_profile = NULL;
+               switch_caller_profile_t *caller_profile = NULL, *orig_caller_profile = NULL;
                char *dest = NULL;
                char *dialplan = NULL;
                char *cid_name = "";
@@ -1893,12 +2085,22 @@ static JSBool session_construct(JSContext *cx, JSObject *obj, uintN argc, jsval
                char *context = "";
                char *username = NULL;
                char *to = NULL;
-               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+
+               *rval = BOOLEAN_TO_JSVAL(JS_FALSE);
 
                if (JS_ValueToObject(cx, argv[0], &session_obj)) {
                        struct js_session *old_jss = NULL;
                        if ((old_jss = JS_GetPrivate(cx, session_obj))) {
                                session = old_jss->session;
+                               orig_caller_profile = switch_channel_get_caller_profile(switch_core_session_get_channel(session));
+                               dialplan = orig_caller_profile->dialplan;
+                               cid_name = orig_caller_profile->caller_id_name;
+                               cid_num = orig_caller_profile->caller_id_number;
+                               ani = orig_caller_profile->ani;
+                               aniii = orig_caller_profile->aniii;
+                               rdnis = orig_caller_profile->rdnis;
+                               context = orig_caller_profile->context;
+                               username = orig_caller_profile->username;
                        }
                }
 
@@ -1906,7 +2108,7 @@ static JSBool session_construct(JSContext *cx, JSObject *obj, uintN argc, jsval
 
                if (!strchr(dest, '/')) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid Channel String\n");
-                       return JS_TRUE;
+                       goto done;
                }
 
                if (argc > 2) {
@@ -1940,7 +2142,6 @@ static JSBool session_construct(JSContext *cx, JSObject *obj, uintN argc, jsval
                        to = JS_GetStringBytes(JS_ValueToString(cx, argv[11]));
                }
                
-               
                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;
@@ -1959,41 +2160,45 @@ static JSBool session_construct(JSContext *cx, JSObject *obj, uintN argc, jsval
                                                                                                   context,
                                                                                                   dest);
                
-               if (switch_ivr_originate(session, &peer_session, &cause, dest, to ? atoi(to) : 60, NULL, NULL, NULL, caller_profile) != SWITCH_STATUS_SUCCESS) {
+               if (switch_ivr_originate(session, &peer_session, &jss->cause, dest, to ? atoi(to) : 60, NULL, NULL, NULL, caller_profile) != SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot Create Outgoing Channel! [%s]\n", dest);
-                       return JS_TRUE;
+                       goto done;
                }
 
-               *rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, switch_channel_cause2str(cause)));
-
-               jss = switch_core_session_alloc(peer_session, sizeof(*jss));
                jss->session = peer_session;
                jss->flags = 0;
-               jss->cx = cx;
-               jss->obj = obj;
-               JS_SetPrivate(cx, obj, jss);
-               switch_set_flag(jss, S_HUP);
+
+               *rval = BOOLEAN_TO_JSVAL(JS_TRUE);
 
        } else {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing Args\n");
        }
 
+ done:
        return JS_TRUE;
 }
 
+
+
+
 static void session_destroy(JSContext *cx, JSObject *obj)
 {
        struct js_session *jss;
+       switch_channel_t *channel = NULL;
        
        if (cx && obj) {
                if ((jss = JS_GetPrivate(cx, obj))) {
-                       if (switch_test_flag(jss, S_HUP)) {
-                               switch_channel_t *channel;
+                       if (jss->session) {
+                               channel = switch_core_session_get_channel(jss->session);
+                               switch_channel_set_private(channel, "jss", NULL);
+                       }
 
-                               if (jss->session) {
-                                       channel = switch_core_session_get_channel(jss->session);
-                                       switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
-                               }
+                       if (channel && switch_test_flag(jss, S_HUP)) {
+                               switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+                       }
+
+                       if (switch_test_flag(jss, S_FREE)) {
+                               free(jss);
                        }
                }
        }
@@ -2073,8 +2278,9 @@ static JSBool fileio_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
        switch_size_t read = 0;
 
        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-
-       if (fio) {
+       
+       if (!fio) {
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
                return JS_TRUE;
        }
 
index e027245f4c3e8db3b0e80bd86494f740e3748181..7f10da5af5af38dba8675117da498659f4b12c86 100644 (file)
@@ -132,6 +132,8 @@ struct js_session {
        JSContext *cx;
        JSObject *obj;
        unsigned int flags;
+       switch_call_cause_t cause;
+       JSFunction *on_hangup;
 };
 
 
index 8cde803e8e0f138c39bc48cba4f4f5693a1b4435..2ab13817e8fefae6ce5e748f2c4c31ca49b2a4e7 100644 (file)
@@ -185,7 +185,6 @@ static void switch_core_standard_on_hold(switch_core_session_t *session);
 /* The main runtime obj we keep this hidden for ourselves */
 static struct switch_core_runtime runtime;
 
-
 static void db_pick_path(char *dbname, char *buf, switch_size_t size)
 {
 
@@ -1835,20 +1834,22 @@ SWITCH_DECLARE(switch_call_cause_t) switch_core_session_outgoing_channel(switch_
 SWITCH_DECLARE(switch_status_t) switch_core_session_answer_channel(switch_core_session_t *session)
 {
        switch_io_event_hook_answer_channel_t *ptr;
-       switch_status_t status = SWITCH_STATUS_FALSE;
+       switch_status_t status = SWITCH_STATUS_SUCCESS;
 
        assert(session != NULL);
+
        if (session->endpoint_interface->io_routines->answer_channel) {
-               if ((status = session->endpoint_interface->io_routines->answer_channel(session)) == SWITCH_STATUS_SUCCESS) {
-                       for (ptr = session->event_hooks.answer_channel; ptr; ptr = ptr->next) {
-                               if ((status = ptr->answer_channel(session)) != SWITCH_STATUS_SUCCESS) {
-                                       break;
-                               }
+               status = session->endpoint_interface->io_routines->answer_channel(session);
+       }
+
+       if (status == SWITCH_STATUS_SUCCESS) {
+               for (ptr = session->event_hooks.answer_channel; ptr; ptr = ptr->next) {
+                       if ((status = ptr->answer_channel(session)) != SWITCH_STATUS_SUCCESS) {
+                               break;
                        }
                }
-       } else {
-               status = SWITCH_STATUS_SUCCESS;
        }
+        
 
        return status;
 }
@@ -1856,19 +1857,23 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_answer_channel(switch_core_s
 SWITCH_DECLARE(switch_status_t) switch_core_session_receive_message(switch_core_session_t *session, switch_core_session_message_t *message)
 {
        switch_io_event_hook_receive_message_t *ptr;
-       switch_status_t status = SWITCH_STATUS_FALSE;
+       switch_status_t status = SWITCH_STATUS_SUCCESS;
 
        assert(session != NULL);
+
        if (session->endpoint_interface->io_routines->receive_message) {
-               if ((status =
-                        session->endpoint_interface->io_routines->receive_message(session, message)) == SWITCH_STATUS_SUCCESS) {
-                       for (ptr = session->event_hooks.receive_message; ptr; ptr = ptr->next) {
-                               if ((status = ptr->receive_message(session, message)) != SWITCH_STATUS_SUCCESS) {
-                                       break;
-                               }
+               status = session->endpoint_interface->io_routines->receive_message(session, message);
+               
+       }
+
+       if (status == SWITCH_STATUS_SUCCESS) {
+               for (ptr = session->event_hooks.receive_message; ptr; ptr = ptr->next) {
+                       if ((status = ptr->receive_message(session, message)) != SWITCH_STATUS_SUCCESS) {
+                               break;
                        }
                }
        }
+
        switch_core_session_kill_channel(session, SWITCH_SIG_BREAK);
        return status;
 }
@@ -2874,6 +2879,31 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_answer_channe
 
 }
 
+SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_state_change(switch_core_session_t *session,
+                                                                                                                                                               switch_answer_channel_hook_t state_change)
+                                                                                                                                                                 
+
+{
+       switch_io_event_hook_state_change_t *hook, *ptr;
+
+       assert(state_change != NULL);
+       if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
+               hook->state_change = state_change;
+               if (!session->event_hooks.state_change) {
+                       session->event_hooks.state_change = hook;
+               } else {
+                       for (ptr = session->event_hooks.state_change; ptr && ptr->next; ptr = ptr->next);
+                       ptr->next = hook;
+
+               }
+
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+       return SWITCH_STATUS_MEMERR;
+
+}
+
 SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_read_frame(switch_core_session_t *session,
                                                                                                                                                        switch_read_frame_hook_t read_frame)
 {
@@ -3216,13 +3246,26 @@ static void switch_core_standard_on_hibernate(switch_core_session_t *session)
 
 SWITCH_DECLARE(void) switch_core_session_signal_state_change(switch_core_session_t *session)
 {
+       switch_status_t status = SWITCH_STATUS_SUCCESS;
+       switch_io_event_hook_state_change_t *ptr;
 
        /* If trylock fails the signal is already awake so we needn't bother */
        if (switch_mutex_trylock(session->mutex) == SWITCH_STATUS_SUCCESS) {
                switch_thread_cond_signal(session->cond);
                switch_mutex_unlock(session->mutex);
        } 
-       
+
+       if (session->endpoint_interface->io_routines->state_change) {
+               status = session->endpoint_interface->io_routines->state_change(session);
+       }
+
+       if (status == SWITCH_STATUS_SUCCESS) {
+               for (ptr = session->event_hooks.state_change; ptr; ptr = ptr->next) {
+                       if ((status = ptr->state_change(session)) != SWITCH_STATUS_SUCCESS) {
+                               break;
+                       }
+               }
+       }
 }
 
 SWITCH_DECLARE(unsigned int) switch_core_session_running(switch_core_session_t *session)