]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
break everything
authorAnthony Minessale <anthony.minessale@gmail.com>
Wed, 1 Mar 2006 22:55:28 +0000 (22:55 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Wed, 1 Mar 2006 22:55:28 +0000 (22:55 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@720 d0543943-73ff-0310-b7d9-9358b9ac24b2

16 files changed:
scripts/multicast/send.pl
src/include/switch_caller.h
src/include/switch_channel.h
src/include/switch_core.h
src/include/switch_types.h
src/mod/applications/mod_bridgecall/mod_bridgecall.c
src/mod/endpoints/mod_exosip/mod_exosip.c
src/mod/endpoints/mod_iax/mod_iax.c
src/mod/endpoints/mod_portaudio/mod_portaudio.c
src/mod/endpoints/mod_wanpipe/mod_wanpipe.c
src/mod/endpoints/mod_woomera/mod_woomera.c
src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
src/switch_caller.c
src/switch_channel.c
src/switch_core.c
src/switch_ivr.c

index 047c70d6cb6dc38c14095fc2868907e00c591499..ed4c84dfe2441cc97c0bf6d584b64f505897f6ca 100755 (executable)
@@ -8,8 +8,10 @@ $ip and $port or die "Usage $0: <ip> <port>\n";
 $socket = new IO::Socket::INET->new( PeerPort => $port,
                                     Proto => 'udp',
                                     PeerAddr => $ip);
-
-my $buf = `cat $file`;
+open(I, $file);
+$/ = undef;
+my $buf = <I>;
+close(I);
 
 $socket->send("$buf\n");
 
index 3a1592aadd9480b7bb7ae005eca0907a75f605dc..00744264822e1d2a4bf9bd44b413ed693c31b6f6 100644 (file)
@@ -134,7 +134,7 @@ extern "C" {
 
        /*!
       \brief Create a new caller profile object
-         \param session session associated with the profile (bound by scope)
+         \param pool memory pool to use
          \param dialplan name of the dialplan module in use
          \param caller_id_name caller ID name
          \param caller_id_number caller ID number
@@ -144,7 +144,7 @@ extern "C" {
          \param destination_number destination number
          \return a new profile object allocated from the session's memory pool
        */
-       SWITCH_DECLARE(switch_caller_profile *) switch_caller_profile_new(switch_core_session *session,
+       SWITCH_DECLARE(switch_caller_profile *) switch_caller_profile_new(switch_memory_pool *pool,
                                                                                                                                          char *dialplan,
                                                                                                                                          char *caller_id_name,
                                                                                                                                          char *caller_id_number,
index 347824e696a7e23cf9c3e5f03ab90e0dd72147ca..008b39a112671a21e8d564182034b09336b23e86 100644 (file)
@@ -65,6 +65,13 @@ typedef struct {
 */
 SWITCH_DECLARE(switch_channel_state) switch_channel_get_state(switch_channel *channel);
 
+/*!
+  \brief Determine if a channel is ready for io
+  \param channel channel to test
+  \return true if the channel is ready
+*/
+SWITCH_DECLARE(unsigned int) switch_channel_ready(switch_channel *channel);
+
 /*!
   \brief Set the current state of a channel
   \param channel channel to set state of
index c3fbefa9ee90145e76864f8cfffbc638f2015217..3b2fc327b3dbca55b9f477b4c6b8b0e04c596d71 100644 (file)
@@ -157,6 +157,12 @@ SWITCH_DECLARE(switch_status) switch_core_destroy_memory_pool(switch_memory_pool
 */
 SWITCH_DECLARE(void) switch_core_session_run(switch_core_session *session);
 
+/*! 
+  \brief determine if the session's state machine is running
+  \param session the session on which to check
+*/
+SWITCH_DECLARE(unsigned int) switch_core_session_runing(switch_core_session *session);
+
 /*! 
   \brief Allocate memory from the main pool with no intention of returning it
   \param memory the number of bytes to allocate
index 5626f1916ebec2622c21f7e4d8d59e7fe31542c0..b9e1b205d3844f52fff27a519cfe945e75295179 100644 (file)
@@ -239,6 +239,8 @@ CF_RECV_AUDIO   = (1 <<  1) - Channel will receive audio
 CF_ANSWERED     = (1 <<  2) - Channel is answered
 CF_OUTBOUND     = (1 <<  3) - Channel is an outbound channel
 CF_EARLY_MEDIA  = (1 <<  4) - Channel is ready for audio before answer 
+CF_ORIGINATOR  = (1 <<  5) - Channel is an originator
+CF_TRANSFER            = (1 <<  6) - Channel is being transfered
 </pre>
  */
 
@@ -247,7 +249,9 @@ typedef enum {
        CF_RECV_AUDIO   = (1 <<  1),
        CF_ANSWERED     = (1 <<  2),
        CF_OUTBOUND     = (1 <<  3),
-       CF_EARLY_MEDIA  = (1 << 4)
+       CF_EARLY_MEDIA  = (1 <<  4),
+       CF_ORIGINATOR   = (1 <<  5),
+       CF_TRANSFER             = (1 <<  6)
 } switch_channel_flag;
 
 
index 1a532084adda77f1b44697d6dc0b0b2f185f59c0..3f064020bffd3296ccd6a3c7d15c7f48228f272d 100644 (file)
@@ -55,7 +55,7 @@ static void audio_bridge_function(switch_core_session *session, char *data)
        }
 
        caller_caller_profile = switch_channel_get_caller_profile(caller_channel);
-       caller_profile = switch_caller_profile_new(session,
+       caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
                                                                                           caller_caller_profile->dialplan,
                                                                                           caller_caller_profile->caller_id_name,
                                                                                           caller_caller_profile->caller_id_number,
index a2efe4da9c8df0d2e205baff781ecf7824be9710..23d6c30b63083a37de947cfac341c54778b97a08 100644 (file)
@@ -550,7 +550,6 @@ static switch_status exosip_read_frame(switch_core_session *session, switch_fram
                           && tech_pvt->read_frame.datalen == 0) {
                        tech_pvt->read_frame.datalen =
                                jrtp4c_read(tech_pvt->rtp_session, tech_pvt->read_frame.data, sizeof(tech_pvt->read_buf), &payload);
-
                        /* RFC2833 ... TBD try harder to honor the duration etc.*/
                        if (payload == 101) {
                                unsigned char *packet = tech_pvt->read_frame.data;
@@ -732,7 +731,6 @@ static switch_status exosip_kill_channel(switch_core_session *session, int sig)
        tech_pvt = switch_core_session_get_private(session);
        assert(tech_pvt != NULL);
 
-
        switch_clear_flag(tech_pvt, TFLAG_IO);
        switch_set_flag(tech_pvt, TFLAG_BYE);
 
@@ -1008,7 +1006,7 @@ static switch_status exosip_create_call(eXosip_event_t * event)
                snprintf(name, sizeof(name), "Exosip/%s-%04x", event->request->from->url->username, rand() & 0xffff);
                switch_channel_set_name(channel, name);
 
-               if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
+               if ((tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
                                                                                                                                  globals.dialplan,
                                                                                                                                  event->request->from->displayname,
                                                                                                                                  event->request->from->url->username,
index a1952674fbb5e8631cfe44526aa1603215abaec2..5168df50a7f2a796ca6d79c4164f915e2ff8ef7f 100644 (file)
@@ -979,7 +979,7 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void)
                                                }
 
 
-                                               if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
+                                               if ((tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
                                                                                                                                                                  globals.dialplan,
                                                                                                                                                                  iaxevent->ies.calling_name,
                                                                                                                                                                  iaxevent->ies.calling_number,
index 412f3d8d6f4a41a6a2692f5e4dd2107a7c4d2bb0..48f251691a3e20a0885c284acb10e12f68b2cbbb 100644 (file)
@@ -808,7 +808,7 @@ static switch_status place_call(char *dest, char *out, size_t outlen)
                        return SWITCH_STATUS_FALSE;
                }
 
-               if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
+               if ((tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
                                                                                                                                  globals.dialplan,
                                                                                                                                  globals.cid_name,
                                                                                                                                  globals.cid_num, NULL, NULL, NULL, dest)) != 0) {
index e88035e3e7acdacbfd85f0ac4495c97dca5bab10..281dd54422aa6503a077862585a46ed41eac81de 100644 (file)
@@ -973,7 +973,7 @@ static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri
                        snprintf(ani2str, 5, "%.2d", event->ring.ani2);
                }
 
-               if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
+               if ((tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
                                                                                                                                  globals.dialplan,
                                                                                                                                  "wanpipe fixme",
                                                                                                                                  event->ring.callingnum,
index c22d569aab5752c1dd993a28a365be6bc7837b64..a605c2286d70bb9218966123ea32f510c87670bb 100644 (file)
@@ -1064,7 +1064,7 @@ static void *woomera_channel_thread_run(switch_thread *thread, void *obj)
                                }
                                ip = woomera_message_header(&wmsg, "Remote-Address");
 
-                               if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
+                               if ((tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
                                                                                                                                                  tech_pvt->profile->dialplan,
                                                                                                                                                  cid_name, cid_num, ip, NULL, NULL, exten)) != 0) {
                                        char name[128];
index 76104e23614723e605ff421887876f3cdc51c115..6bb8408b99a2f099d091a9a37d98333fa7fc12c3 100644 (file)
@@ -63,6 +63,8 @@
 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 struct {
        size_t gStackChunkSize;
@@ -86,6 +88,10 @@ typedef enum {
        TTF_DTMF = (1 << 0)
 } teletone_flag_t;
 
+typedef enum {
+       S_HUP = (1 << 0)
+} session_flag_t;
+
 struct dtmf_callback_state {
        struct js_session *session_state;
        char code_buffer[1024];
@@ -100,6 +106,7 @@ struct js_session {
        switch_core_session *session;
        JSContext *cx;
        JSObject *obj;
+       switch_memory_pool *pool;
        unsigned int flags;
 };
 
@@ -407,7 +414,7 @@ static JSBool session_recordfile(JSContext *cx, JSObject *obj, uintN argc, jsval
        switch_ivr_record_file(jss->session, &fh, file_name, dtmf_func, bp, len);
        *rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, cb_state.ret_buffer));
 
-       return (switch_channel_get_state(channel) == CS_EXECUTE) ? JS_TRUE : JS_FALSE;
+       return (switch_channel_ready(channel)) ? JS_TRUE : JS_FALSE;
 }
 
 static JSBool session_streamfile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
@@ -459,7 +466,7 @@ static JSBool session_streamfile(JSContext *cx, JSObject *obj, uintN argc, jsval
        switch_ivr_play_file(jss->session, &fh, file_name, timer_name, dtmf_func, bp, len);
        *rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, cb_state.ret_buffer));
 
-       return (switch_channel_get_state(channel) == CS_EXECUTE) ? JS_TRUE : JS_FALSE;
+       return (switch_channel_ready(channel)) ? JS_TRUE : JS_FALSE;
 }
 
 static JSBool session_speak(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
@@ -520,7 +527,7 @@ static JSBool session_speak(JSContext *cx, JSObject *obj, uintN argc, jsval *arg
 
        *rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, cb_state.ret_buffer));
 
-       return (switch_channel_get_state(channel) == CS_EXECUTE) ? JS_TRUE : JS_FALSE;
+       return (switch_channel_ready(channel)) ? JS_TRUE : JS_FALSE;
 }
 
 static JSBool session_get_digits(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
@@ -566,6 +573,59 @@ static JSBool session_answer(JSContext *cx, JSObject *obj, uintN argc, jsval *ar
        return JS_TRUE;
 }
 
+static JSBool session_ready(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       struct js_session *jss = JS_GetPrivate(cx, obj);
+       switch_channel *channel;
+
+       channel = switch_core_session_get_channel(jss->session);
+       assert(channel != NULL);
+       *rval = BOOLEAN_TO_JSVAL( switch_channel_ready(channel) ? JS_TRUE : JS_FALSE );
+
+       return JS_TRUE;
+}
+
+static JSBool session_wait_for_answer(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       struct js_session *jss = JS_GetPrivate(cx, obj);
+       switch_channel *channel;
+       switch_time_t started;
+       unsigned int elapsed;
+       channel = switch_core_session_get_channel(jss->session);
+       assert(channel != NULL);
+       int32 timeout = 60;
+       started = switch_time_now();
+
+       if (argc > 0) {
+               JS_ValueToInt32(cx, argv[0], &timeout);
+       }
+
+       for(;;) {
+               elapsed = (unsigned int)((switch_time_now() - started) / 1000);
+               if ((int32)elapsed > timeout || switch_channel_test_flag(channel, CF_ANSWERED) ||
+                       switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
+                       break;
+               }
+               
+               switch_yield(1000);
+       }
+
+       return JS_TRUE;
+}
+
+static JSBool session_hangup(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       struct js_session *jss = JS_GetPrivate(cx, obj);
+       switch_channel *channel;
+
+       channel = switch_core_session_get_channel(jss->session);
+       assert(channel != NULL);
+
+       switch_channel_hangup(channel);
+       switch_core_session_kill_channel(jss->session, SWITCH_SIG_KILL);
+       return JS_TRUE;
+}
+
 #ifdef HAVE_CURL
 
 struct config_data {
@@ -658,7 +718,8 @@ static JSBool js_fetchurl(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
 /* Session Object */
 /*********************************************************************************/
 enum session_tinyid {
-    SESSION_NAME, SESSION_STATE
+    SESSION_NAME, SESSION_STATE,
+       PROFILE_DIALPLAN, PROFILE_CID_NAME, PROFILE_CID_NUM, PROFILE_IP, PROFILE_ANI, PROFILE_ANI2, PROFILE_DEST
 };
 
 static JSFunctionSpec session_methods[] = {
@@ -667,6 +728,9 @@ static JSFunctionSpec session_methods[] = {
     {"speak", session_speak, 1}, 
     {"getDigits", session_get_digits, 1},
     {"answer", session_answer, 0}, 
+    {"ready", session_ready, 0}, 
+    {"waitForAnswer", session_wait_for_answer, 0}, 
+    {"hangup", session_hangup, 0}, 
        {0}
 };
 
@@ -674,6 +738,13 @@ static JSFunctionSpec session_methods[] = {
 static JSPropertySpec session_props[] = {
     {"name", SESSION_NAME, JSPROP_READONLY|JSPROP_PERMANENT}, 
     {"state", SESSION_STATE, JSPROP_READONLY|JSPROP_PERMANENT}, 
+    {"dialplan", PROFILE_DIALPLAN, JSPROP_READONLY|JSPROP_PERMANENT},
+       {"caller_id_name", PROFILE_CID_NAME, JSPROP_READONLY|JSPROP_PERMANENT}, 
+    {"caller_id_num", PROFILE_CID_NUM, JSPROP_READONLY|JSPROP_PERMANENT}, 
+    {"network_addr", PROFILE_IP, JSPROP_READONLY|JSPROP_PERMANENT}, 
+    {"ani", PROFILE_ANI, JSPROP_READONLY|JSPROP_PERMANENT}, 
+    {"ani2", PROFILE_ANI2, JSPROP_READONLY|JSPROP_PERMANENT}, 
+    {"destination", PROFILE_DEST, JSPROP_READONLY|JSPROP_PERMANENT}, 
     {0}
 };
 
@@ -683,11 +754,14 @@ static JSBool session_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval
        int param = 0;
        JSBool res = JS_TRUE;
        switch_channel *channel;
+       switch_caller_profile *caller_profile;
        char *name;
 
        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) {
@@ -701,7 +775,42 @@ static JSBool session_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval
                *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, switch_channel_get_name(channel)));
                break;
        case SESSION_STATE:
-               *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, switch_channel_state_name(switch_channel_get_state(channel)) ));
+               *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, switch_channel_state_name(switch_channel_get_state(channel))));
+               break;
+       case PROFILE_DIALPLAN:
+               if (caller_profile) {
+                       *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, caller_profile->dialplan));
+               }
+               break;
+       case PROFILE_CID_NAME:
+               if (caller_profile) {
+                       *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, caller_profile->caller_id_name));
+               }
+               break;
+       case PROFILE_CID_NUM:
+               if (caller_profile) {
+                       *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, caller_profile->caller_id_number));
+               }
+               break;
+       case PROFILE_IP:
+               if (caller_profile) {
+                       *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, caller_profile->network_addr));
+               }
+               break;
+       case PROFILE_ANI:
+               if (caller_profile) {
+                       *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, caller_profile->ani));
+               }
+               break;
+       case PROFILE_ANI2:
+               if (caller_profile) {
+                       *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, caller_profile->ani2));
+               }
+               break;
+       case PROFILE_DEST:
+               if (caller_profile) {
+                       *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, caller_profile->destination_number));
+               }
                break;
        default:
                res = JS_FALSE;
@@ -715,7 +824,8 @@ static JSBool session_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval
 JSClass session_class = {
     "Session", JSCLASS_HAS_PRIVATE, 
        JS_PropertyStub,  JS_PropertyStub,  session_getProperty,  JS_PropertyStub, 
-    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   JS_FinalizeStub
+    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   session_destroy, NULL, NULL, NULL,
+       session_construct
 };
 
 
@@ -752,6 +862,117 @@ static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map
        return 0;
 }
 
+/* Session Object */
+/*********************************************************************************/
+static JSBool session_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       switch_memory_pool *pool = NULL;
+       int need_pool = 1;
+       if (argc > 2) {
+               struct js_session *jss = NULL;
+               JSObject *session_obj;
+               switch_core_session *session = NULL, *peer_session = NULL;
+               switch_caller_profile *caller_profile = NULL;
+               char *channel_type = NULL;
+               char *dest = NULL;
+               char *dialplan = NULL;
+               char *cid_name = "";
+               char *cid_num = "";
+               char *network_addr = "";
+               char *ani = "";
+               char *ani2 = "";
+
+               
+               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;
+                               pool = switch_core_session_get_pool(session);
+                               need_pool = 0;
+                       }
+               }
+
+               channel_type = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
+               dest = JS_GetStringBytes(JS_ValueToString(cx, argv[2]));
+
+               if (argc > 3) {
+                       dialplan = JS_GetStringBytes(JS_ValueToString(cx, argv[3]));
+               }
+               if (argc > 4) {
+                       cid_name = JS_GetStringBytes(JS_ValueToString(cx, argv[4]));
+               }
+               if (argc > 5) {
+                       cid_num = JS_GetStringBytes(JS_ValueToString(cx, argv[5]));
+               }
+               if (argc > 6) {
+                       network_addr = JS_GetStringBytes(JS_ValueToString(cx, argv[6]));
+               }
+               if (argc > 7) {
+                       ani = JS_GetStringBytes(JS_ValueToString(cx, argv[7]));
+               }
+               if (argc > 8) {
+                       ani2 = JS_GetStringBytes(JS_ValueToString(cx, argv[8]));
+               }
+               
+               if (need_pool) {
+                       if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
+                               switch_console_printf(SWITCH_CHANNEL_CONSOLE, "OH OH no pool\n");
+                               return JS_FALSE;
+                       }
+               }
+
+               caller_profile = switch_caller_profile_new(pool, dialplan, cid_name, cid_num, network_addr, ani, ani2, dest);
+               if (switch_core_session_outgoing_channel(session, channel_type, caller_profile, &peer_session) == SWITCH_STATUS_SUCCESS) {
+                       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);
+                       if (need_pool) {
+                               jss->pool = pool;
+                       }
+                       switch_core_session_thread_launch(peer_session);
+                       switch_set_flag(jss, S_HUP);
+                       
+                       return JS_TRUE;
+               } else {
+                       switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Cannot Create Channel\n");
+               }
+       } else {
+               switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Missing Args\n");
+       }
+
+       if (need_pool) {
+               switch_core_destroy_memory_pool(&pool);
+       }
+       return JS_FALSE;
+}
+
+static void session_destroy(JSContext *cx, JSObject *obj)
+{
+       struct js_session *jss;
+       
+       if (cx && obj) {
+               if ((jss = JS_GetPrivate(cx, obj))) {
+                       if (jss->pool) {
+                               switch_core_destroy_memory_pool(&jss->pool);
+                       }
+       
+                       if (switch_test_flag(jss, S_HUP)) {
+                               switch_channel *channel;
+
+                               if (jss->session) {
+                                       channel = switch_core_session_get_channel(jss->session);
+                                       switch_channel_hangup(channel);
+                               }
+                       }
+               }
+       }
+               
+       return;
+}
+
 /* TeleTone Object */
 /*********************************************************************************/
 static JSBool teletone_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
@@ -1072,6 +1293,42 @@ static int write_buf(int fd, char *buf) {
        return 1;
 }
 
+static JSBool js_bridge(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       struct js_session *jss_a = NULL, *jss_b = NULL;
+       JSObject *session_obj_a = NULL, *session_obj_b = NULL;
+       int32 timelimit = 60;
+
+       if (argc > 1) {
+               if (JS_ValueToObject(cx, argv[0], &session_obj_a)) {
+                       if (!(jss_a = JS_GetPrivate(cx, session_obj_a))) {
+                               switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Cannot Find Session [1]\n");
+                               return JS_FALSE;
+                       }
+               } 
+               if (JS_ValueToObject(cx, argv[1], &session_obj_b)) {
+                       if (!(jss_b = JS_GetPrivate(cx, session_obj_b))) {
+                               switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Cannot Find Session [1]\n");
+                               return JS_FALSE;
+                       }
+               } 
+       }
+       
+       if (argc > 3) {
+               if (!JS_ValueToInt32(cx, argv[3], &timelimit)) {
+                       switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Cannot Convert to INT\n");
+                       return JS_FALSE;
+               }
+       }
+       if (!(jss_a && jss_b)) {
+               switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Failure! %s %s\n", jss_a ? "y" : "n", jss_b ? "y" : "n");
+               return JS_FALSE;
+       }
+
+       switch_ivr_multi_threaded_bridge(jss_a->session, jss_b->session, timelimit, NULL, NULL, NULL);
+       return JS_TRUE;
+}
+
 static JSBool js_email(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
        char *to = NULL, *from = NULL, *headers, *body = NULL, *file = NULL;
@@ -1195,6 +1452,7 @@ static JSFunctionSpec fs_functions[] = {
        {"console_log", js_log, 2}, 
        {"include", js_include, 1}, 
        {"email", js_email, 2}, 
+       {"bridge", js_bridge, 2},
 #ifdef HAVE_CURL
        {"fetchURL", js_fetchurl, 1}, 
 #endif 
@@ -1231,6 +1489,40 @@ static int eval_some_js(char *code, JSContext *cx, JSObject *obj, jsval *rval)
        return res;
 }
 
+static int env_init(JSContext *cx, JSObject *javascript_object)
+{
+
+       JS_DefineFunctions(cx, javascript_object, fs_functions);
+
+       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,
+                                NULL,
+                                &session_class,
+                                session_construct,
+                                3,
+                                session_props,
+                                session_methods,
+                                session_props,
+                                session_methods
+                                );
+
+       return 1;
+}
+
 static void js_exec(switch_core_session *session, char *data)
 {
        char *code, *next, *arg, *nextarg;
@@ -1270,28 +1562,14 @@ static void js_exec(switch_core_session *session, char *data)
     if ((cx = JS_NewContext(globals.rt, globals.gStackChunkSize))) {
                JS_SetErrorReporter(cx, js_error);
                if ((javascript_global_object = JS_NewObject(cx, &global_class, NULL, NULL)) && 
-                       JS_DefineFunctions(cx, javascript_global_object, fs_functions) &&
-                       JS_InitStandardClasses(cx, javascript_global_object) &&
+                       env_init(cx, javascript_global_object) &&
                        (session_obj = new_js_session(cx, javascript_global_object, session, &jss, "session", flags))) {
                        JS_SetGlobalObject(cx, javascript_global_object);
                        JS_SetPrivate(cx, javascript_global_object, session);
                        res = 0;
        
 
-                       JS_InitClass(cx,
-                                                javascript_global_object,
-                                                NULL,
-                                                &teletone_class,
-                                                teletone_construct,
-                                                3,
-                                                teletone_props,
-                                                teletone_methods,
-                                                teletone_props,
-                                                teletone_methods
-                                                );
-
-
-
+                       
                        do {
                                if ((next = strchr(code, '|'))) {
                                        *next = '\0';
@@ -1330,6 +1608,89 @@ static void js_exec(switch_core_session *session, char *data)
        }
 }
 
+static void *js_thread_run(switch_thread *thread, void *obj)
+{
+       JSContext *cx = NULL;
+       JSObject *javascript_global_object = NULL;
+       cx = JS_NewContext(globals.rt, globals.gStackChunkSize);
+       char buf[1024];
+       char *code, *next, *arg, *nextarg;
+       jsval rval;
+       int x = 0;
+       char *input_code = obj;
+
+       javascript_global_object = JS_NewObject(cx, &global_class, NULL, NULL);
+       env_init(cx, javascript_global_object);
+       code = input_code;
+
+       do {
+               if ((next = strchr(code, '|'))) {
+                       *next = '\0';
+                       next++;
+               }
+               if ((arg = strchr(code, ':'))) {
+                       int y;
+                       for (y=0;(arg=strchr(arg, ':'));y++)
+                               arg++;
+                       arg = strchr(code, ':');
+                       *arg = '\0';
+                       arg++;
+                       snprintf(buf, sizeof(buf), "~var Argv = new Array(%d);", y);
+                       eval_some_js(buf, cx, javascript_global_object, &rval);
+                       snprintf(buf, sizeof(buf), "~var argc = %d", y);
+                       eval_some_js(buf, cx, javascript_global_object, &rval);
+                       do {
+                               if ((nextarg = strchr(arg, ':'))) {
+                                       *nextarg = '\0';
+                                       nextarg++;
+                               }
+                               snprintf(buf, sizeof(buf), "~Argv[%d] = \"%s\";", x++, arg);
+                               eval_some_js(buf, cx, javascript_global_object, &rval);
+                               arg = nextarg;
+                       } while (arg);
+               }
+               if (!eval_some_js(code, cx, javascript_global_object, &rval)) {
+                       break;
+               }
+               code = next;
+       } while (code);
+
+       if (input_code) {
+               free(input_code);
+       }
+       return NULL;
+}
+
+
+static switch_memory_pool *module_pool = NULL;
+
+static void js_thread_launch(char *text)
+{
+       switch_thread *thread;
+       switch_threadattr_t *thd_attr = NULL;
+
+       if (!module_pool) {
+               if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) {
+                       switch_console_printf(SWITCH_CHANNEL_CONSOLE, "OH OH no pool\n");
+                       return;
+               }
+       }
+       
+       switch_threadattr_create(&thd_attr, module_pool);
+       switch_threadattr_detach_set(thd_attr, 1);
+       switch_thread_create(&thread, thd_attr, js_thread_run, strdup(text), module_pool);
+}
+
+
+static switch_status launch_async(char *text, char *out, size_t outlen)
+{
+
+       js_thread_launch(text);
+       switch_copy_string(out, "OK", outlen);
+       return SWITCH_STATUS_SUCCESS;
+}
+
+
 static const switch_application_interface ivrtest_application_interface = {
        /*.interface_name */ "javascript",
        /*.application_function */ js_exec,
@@ -1337,6 +1698,12 @@ static const switch_application_interface ivrtest_application_interface = {
        /*.next*/ NULL
 };
 
+static struct switch_api_interface js_run_interface = {
+       /*.interface_name */ "jsrun",
+       /*.desc */ "run a script",
+       /*.function */ launch_async,
+       /*.next */ NULL
+};
 
 static switch_loadable_module_interface spidermonkey_module_interface = {
        /*.module_name */ modname,
@@ -1345,7 +1712,7 @@ static switch_loadable_module_interface spidermonkey_module_interface = {
        /*.dialplan_interface */ NULL,
        /*.codec_interface */ NULL,
        /*.application_interface */ &ivrtest_application_interface,
-       /*.api_interface */ NULL,
+       /*.api_interface */ &js_run_interface,
        /*.file_interface */ NULL,
        /*.speech_interface */ NULL,
        /*.directory_interface */ NULL
index 266b1742af2cbf02379c4306f2b8bf3d4302a364..b28afedab6e170ee45bf0b230653e37618f6c722 100644 (file)
@@ -31,7 +31,7 @@
  */
 #include <switch_caller.h>
 
-SWITCH_DECLARE(switch_caller_profile *) switch_caller_profile_new(switch_core_session *session,
+SWITCH_DECLARE(switch_caller_profile *) switch_caller_profile_new(switch_memory_pool *pool,
                                                                                                                                  char *dialplan,
                                                                                                                                  char *caller_id_name,
                                                                                                                                  char *caller_id_number,
@@ -42,14 +42,14 @@ SWITCH_DECLARE(switch_caller_profile *) switch_caller_profile_new(switch_core_se
 
        switch_caller_profile *profile = NULL;
 
-       if ((profile = switch_core_session_alloc(session, sizeof(switch_caller_profile))) != 0) {
-               profile->dialplan = switch_core_session_strdup(session, dialplan);
-               profile->caller_id_name = switch_core_session_strdup(session, caller_id_name);
-               profile->caller_id_number = switch_core_session_strdup(session, caller_id_number);
-               profile->network_addr = switch_core_session_strdup(session, network_addr);
-               profile->ani = switch_core_session_strdup(session, ani);
-               profile->ani2 = switch_core_session_strdup(session, ani2);
-               profile->destination_number = switch_core_session_strdup(session, destination_number);
+       if ((profile = switch_core_alloc(pool, sizeof(switch_caller_profile))) != 0) {
+               profile->dialplan = switch_core_strdup(pool, dialplan);
+               profile->caller_id_name = switch_core_strdup(pool, caller_id_name);
+               profile->caller_id_number = switch_core_strdup(pool, caller_id_number);
+               profile->network_addr = switch_core_strdup(pool, network_addr);
+               profile->ani = switch_core_strdup(pool, ani);
+               profile->ani2 = switch_core_strdup(pool, ani2);
+               profile->destination_number = switch_core_strdup(pool, destination_number);
        }
 
        return profile;
index ee0def55fe25ec1322ce941cca67c38bc6e2c9f0..188e7e4734c644740ef3c4fdd764ad9b6ea48238 100644 (file)
@@ -248,6 +248,12 @@ SWITCH_DECLARE(switch_channel_state) switch_channel_get_state(switch_channel *ch
        return channel->state;
 }
 
+SWITCH_DECLARE(unsigned int) switch_channel_ready(switch_channel *channel)
+{
+       assert(channel != NULL);
+       return (channel->state > CS_RING && channel->state < CS_HANGUP) ? 1 : 0;
+}
+
 static const char *state_names[] = {
        "CS_NEW",
        "CS_INIT",
index 1246212e043e2470baa956c7286d369792f4d0bf..231857aa1a9b04d8e73e87cf8ce6d60f9b7712b8 100644 (file)
@@ -42,6 +42,7 @@ EXTERN_C void xs_init(pTHX);
 struct switch_core_session {
        unsigned long id;
        char name[80];
+       int thread_running;
        switch_memory_pool *pool;
        switch_channel *channel;
        switch_thread *thread;
@@ -714,9 +715,9 @@ SWITCH_DECLARE(char *) switch_core_session_strdup(switch_core_session *session,
        assert(session != NULL);
        assert(session->pool != NULL);
 
-       if (!todup)
+       if (!todup) {
                return NULL;
-
+       }
        len = strlen(todup) + 1;
 
        if (todup && (duped = apr_palloc(session->pool, len)) != 0) {
@@ -731,10 +732,11 @@ SWITCH_DECLARE(char *) switch_core_strdup(switch_memory_pool *pool, char *todup)
        char *duped = NULL;
        size_t len;
        assert(pool != NULL);
-       assert(todup != NULL);
 
-       if (!todup)
+       if (!todup) {
                return NULL;
+       }
+       
        len = strlen(todup) + 1;
 
        if (todup && (duped = apr_palloc(pool, len)) != 0) {
@@ -792,9 +794,11 @@ SWITCH_DECLARE(switch_status) switch_core_session_outgoing_channel(switch_core_s
                if ((status =
                         endpoint_interface->io_routines->outgoing_channel(session, caller_profile,
                                                                                                                           new_session)) == SWITCH_STATUS_SUCCESS) {
-                       for (ptr = session->event_hooks.outgoing_channel; ptr; ptr = ptr->next) {
-                               if ((status = ptr->outgoing_channel(session, caller_profile, *new_session)) != SWITCH_STATUS_SUCCESS) {
-                                       break;
+                       if (session) {
+                               for (ptr = session->event_hooks.outgoing_channel; ptr; ptr = ptr->next) {
+                                       if ((status = ptr->outgoing_channel(session, caller_profile, *new_session)) != SWITCH_STATUS_SUCCESS) {
+                                               break;
+                                       }
                                }
                        }
                } else {
@@ -806,7 +810,7 @@ SWITCH_DECLARE(switch_status) switch_core_session_outgoing_channel(switch_core_s
                switch_caller_profile *profile = NULL, *peer_profile = NULL, *cloned_profile = NULL;
                switch_channel *channel = NULL, *peer_channel = NULL;
 
-               if ((channel = switch_core_session_get_channel(session)) != 0) {
+               if (session && (channel = switch_core_session_get_channel(session)) != 0) {
                        profile = switch_channel_get_caller_profile(channel);
                }
                if ((peer_channel = switch_core_session_get_channel(*new_session)) != 0) {
@@ -820,7 +824,7 @@ SWITCH_DECLARE(switch_status) switch_core_session_outgoing_channel(switch_core_s
                                }
                        }
                        if (peer_profile) {
-                               if ((cloned_profile = switch_caller_profile_clone(session, peer_profile)) != 0) {
+                               if (session && (cloned_profile = switch_caller_profile_clone(session, peer_profile)) != 0) {
                                        switch_channel_set_originatee_caller_profile(channel, cloned_profile);
                                }
                        }
@@ -1536,7 +1540,7 @@ SWITCH_DECLARE(switch_status) switch_core_new_memory_pool(switch_memory_pool **p
                return SWITCH_STATUS_MEMERR;
        }
 
-       if ((apr_pool_create(pool, runtime.memory_pool)) != APR_SUCCESS) {
+       if ((apr_pool_create(pool, runtime.memory_pool)) != SWITCH_STATUS_SUCCESS) {
                *pool = NULL;
                return SWITCH_STATUS_MEMERR;
        }
@@ -1574,6 +1578,12 @@ static void switch_core_standard_on_ring(switch_core_session *session)
 
        switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Standard RING %s\n", switch_channel_get_name(session->channel));
 
+
+       if (switch_channel_test_flag(session->channel, CF_OUTBOUND)) {
+               switch_channel_set_state(session->channel, CS_TRANSMIT);
+               return;
+       }
+
        if ((caller_profile = switch_channel_get_caller_profile(session->channel)) == 0) {
                switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't get profile!\n");
                switch_channel_set_state(session->channel, CS_HANGUP);
@@ -1656,6 +1666,11 @@ SWITCH_DECLARE(void) switch_core_session_signal_state_change(switch_core_session
        switch_thread_cond_signal(session->cond);
 }
 
+SWITCH_DECLARE(unsigned int) switch_core_session_runing(switch_core_session *session)
+{
+       return session->thread_running;
+}
+
 SWITCH_DECLARE(void) switch_core_session_run(switch_core_session *session)
 {
        switch_channel_state state = CS_NEW, laststate = CS_HANGUP, midstate = CS_DONE;
@@ -1679,8 +1694,8 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session *session)
 
         */
        assert(session != NULL);
-
-
+       
+       session->thread_running = 1;
        endpoint_interface = session->endpoint_interface;
        assert(endpoint_interface != NULL);
 
@@ -1943,7 +1958,7 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session *session)
                        switch_thread_cond_wait(session->cond, session->mutex);
                } 
        }
-
+       session->thread_running = 0;
 }
 
 SWITCH_DECLARE(void) switch_core_session_destroy(switch_core_session **session)
@@ -2065,10 +2080,11 @@ SWITCH_DECLARE(void) switch_core_session_thread_launch(switch_core_session *sess
        switch_threadattr_create(&thd_attr, session->pool);
        switch_threadattr_detach_set(thd_attr, 1);
 
-       if (switch_thread_create(&thread, thd_attr, switch_core_session_thread, session, session->pool) != APR_SUCCESS) {
-               switch_core_session_destroy(&session);
+       if (! session->thread_running) {
+               if (switch_thread_create(&thread, thd_attr, switch_core_session_thread, session, session->pool) != SWITCH_STATUS_SUCCESS) {
+                       switch_core_session_destroy(&session);
+               }
        }
-
 }
 
 SWITCH_DECLARE(void) switch_core_session_launch_thread(switch_core_session *session, switch_thread_start_t func,
@@ -2227,12 +2243,12 @@ SWITCH_DECLARE(switch_status) switch_core_init(char *console)
        }
 
        /* INIT APR and Create the pool context */
-       if (apr_initialize() != APR_SUCCESS) {
+       if (apr_initialize() != SWITCH_STATUS_SUCCESS) {
                apr_terminate();
                return SWITCH_STATUS_MEMERR;
        }
 
-       if (apr_pool_create(&runtime.memory_pool, NULL) != APR_SUCCESS) {
+       if (apr_pool_create(&runtime.memory_pool, NULL) != SWITCH_STATUS_SUCCESS) {
                switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Could not allocate memory pool\n");
                switch_core_destroy();
                return SWITCH_STATUS_MEMERR;
index a1c30f0e5594352627bc2e14bed806da3f41d6f3..4a98b8874659c72930b406afc88ea1a8b8bcaf60 100644 (file)
@@ -50,7 +50,7 @@ SWITCH_DECLARE(switch_status) switch_ivr_collect_digits_callback(switch_core_ses
                return SWITCH_STATUS_GENERR;
        }
 
-       while (switch_channel_get_state(channel) == CS_EXECUTE) {
+       while(switch_channel_ready(channel)) {
                switch_frame *read_frame;
                char dtmf[128];
 
@@ -105,7 +105,8 @@ SWITCH_DECLARE(switch_status) switch_ivr_collect_digits_count(switch_core_sessio
        if (timeout) {
                started = switch_time_now();
        }
-       while (switch_channel_get_state(channel) == CS_EXECUTE) {
+
+       while(switch_channel_ready(channel)) {
                switch_frame *read_frame;
 
                if (timeout) {
@@ -161,7 +162,7 @@ SWITCH_DECLARE(switch_status) switch_ivr_record_file(switch_core_session *sessio
        switch_codec codec, *read_codec;
        char *codec_name;
        switch_status status = SWITCH_STATUS_SUCCESS;
-       
+
        if (!fh) {
                fh = &lfh;
        }
@@ -206,7 +207,7 @@ SWITCH_DECLARE(switch_status) switch_ivr_record_file(switch_core_session *sessio
        }
        
 
-       while (switch_channel_get_state(channel) == CS_EXECUTE) {
+       while(switch_channel_ready(channel)) {
                size_t len;
 
                if (dtmf_callback || buf) {
@@ -267,7 +268,7 @@ SWITCH_DECLARE(switch_status) switch_ivr_play_file(switch_core_session *session,
        int stream_id;
        switch_status status = SWITCH_STATUS_SUCCESS;
        switch_file_handle lfh;
-       
+
        if (!fh) {
                fh = &lfh;
                memset(fh, 0, sizeof(lfh));
@@ -332,7 +333,7 @@ SWITCH_DECLARE(switch_status) switch_ivr_play_file(switch_core_session *session,
        }
 
        ilen = samples;
-       while (switch_channel_get_state(channel) == CS_EXECUTE) {
+       while(switch_channel_ready(channel)) {
                int done = 0;
                int do_speed = 1;
                int last_speed = -1;
@@ -586,8 +587,7 @@ SWITCH_DECLARE(switch_status) switch_ivr_speak_text(switch_core_session *session
        }
 
        ilen = len;
-       while (switch_channel_get_state(channel) == CS_EXECUTE) {
-
+       while(switch_channel_ready(channel)) {
                if (dtmf_callback || buf) {
 
 
@@ -667,7 +667,6 @@ SWITCH_DECLARE(switch_status) switch_ivr_speak_text(switch_core_session *session
        switch_console_printf(SWITCH_CHANNEL_CONSOLE, "done speaking text\n");
        switch_core_codec_destroy(&codec);
        flags = 0;
-       switch_core_codec_destroy(&codec);
 
        if (timer_name) {
                /* End the audio absorbing thread */
@@ -798,9 +797,11 @@ static switch_status audio_bridge_on_hangup(switch_core_session *session)
        switch_console_printf(SWITCH_CHANNEL_CONSOLE, "CUSTOM HANGUP %s kill %s\n", switch_channel_get_name(channel),
                                                  switch_channel_get_name(other_channel));
 
-       switch_core_session_kill_channel(other_session, SWITCH_SIG_KILL);
-       switch_core_session_kill_channel(session, SWITCH_SIG_KILL);
-
+       //switch_core_session_kill_channel(other_session, SWITCH_SIG_KILL);
+       //switch_core_session_kill_channel(session, SWITCH_SIG_KILL);
+       if (switch_channel_test_flag(channel, CF_ORIGINATOR) && !switch_channel_test_flag(other_channel, CF_TRANSFER)) {
+               switch_core_session_kill_channel(other_session, SWITCH_SIG_KILL);
+       }
        return SWITCH_STATUS_SUCCESS;
 }
 
@@ -855,6 +856,7 @@ SWITCH_DECLARE(switch_status) switch_ivr_multi_threaded_bridge(switch_core_sessi
        switch_channel *caller_channel, *peer_channel;
        time_t start;
        int stream_id = 0;
+       switch_frame *read_frame;
 
        caller_channel = switch_core_session_get_channel(session);
        assert(caller_channel != NULL);
@@ -895,12 +897,15 @@ SWITCH_DECLARE(switch_status) switch_ivr_multi_threaded_bridge(switch_core_sessi
        }
 
        time(&start);
-       while (switch_channel_get_state(caller_channel) == CS_EXECUTE &&
-                  switch_channel_get_state(peer_channel) == CS_TRANSMIT &&
+       while (switch_channel_ready(caller_channel) &&
+                  switch_channel_ready(peer_channel) &&
                   !switch_channel_test_flag(peer_channel, CF_ANSWERED) &&
                   !switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA) &&
                   ((time(NULL) - start) < timelimit)) {
-               switch_yield(20000);
+               if (switch_core_session_read_frame(session, &read_frame, 1000, 0) != SWITCH_STATUS_SUCCESS) {
+                       break;
+               }
+               switch_yield(1000);
        }
 
        if (switch_channel_test_flag(peer_channel, CF_ANSWERED)) {
@@ -913,7 +918,7 @@ SWITCH_DECLARE(switch_status) switch_ivr_multi_threaded_bridge(switch_core_sessi
                switch_core_session_launch_thread(session, audio_bridge_thread, (void *) &other_audio_thread);
                audio_bridge_thread(NULL, (void *) &this_audio_thread);
 
-               switch_channel_hangup(peer_channel);
+               //switch_channel_hangup(peer_channel);
                if (other_audio_thread.running > 0) {
                        other_audio_thread.running = -1;
                        /* wait for the other audio thread */