]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Upgrade Dingaling to meet new googletalk spec upgrade your client if you have issues.
authorAnthony Minessale <anthony.minessale@gmail.com>
Fri, 18 Aug 2006 01:28:50 +0000 (01:28 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Fri, 18 Aug 2006 01:28:50 +0000 (01:28 +0000)
codecs need more work...

Expose events into javascript so you can create and fire events and
and pick up chat events with chat-enabled clients like googletalk
EXAMPLE:

session.answer();

e = new Event("custom", "JS::Custom");
e.addHeader("subject", "cool");
e.addBody("hello this is a test");
e.fire;

while(session.ready()) {
    session.execute("sleep", "1000");
    event = session.getEvent();
    if (event) {
      str = event.serialize(); // or ("xml")
      console_log("debug", "Dump Event:\n" + str + "\n");

        e = new Event("custom", "JS::Chat");
        e.addHeader("works", "yes");
        e.addBody("you said: " + event.getBody());
        session.sendEvent(e);
      event.destroy();
    }
}

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

libs/libdingaling/src/libdingaling.c
libs/libdingaling/src/libdingaling.h
src/include/switch_core.h
src/include/switch_event.h
src/mod/codecs/mod_speex/mod_speex.c
src/mod/endpoints/mod_dingaling/mod_dingaling.c
src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
src/switch_core.c
src/switch_event.c
src/switch_xml.c

index 9e8bb4762e871ee8f685d32426cfa5a54586e560..cbb95bbe83ff041a9c32758cc0b8ed0e6e853737 100644 (file)
@@ -190,6 +190,11 @@ char *ldl_session_get_id(ldl_session_t *session)
        return session->id;
 }
 
+void ldl_session_send_msg(ldl_session_t *session, char *subject, char *body)
+{
+       ldl_handle_send_msg(session->handle, session->them, subject, body);
+}
+
 ldl_status ldl_session_destroy(ldl_session_t **session_p)
 {
        ldl_session_t *session = *session_p;
@@ -277,7 +282,7 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
        while(xml) {
                char *type = xtype ? xtype : iks_find_attrib(xml, "type");
                iks *tag;
-
+               
                if (type) {
                        
                        if (!strcasecmp(type, "initiate") || !strcasecmp(type, "accept")) {
@@ -298,7 +303,7 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
                                                        if (!strcasecmp(iks_name(itag), "payload-type") && session->payload_len < LDL_MAX_PAYLOADS) {
                                                                char *name = iks_find_attrib(itag, "name");
                                                                char *id = iks_find_attrib(itag, "id");
-                                                               char *rate = iks_find_attrib(itag, "rate");
+                                                               char *rate = iks_find_attrib(itag, "clockrate");
                                                                if (name && id) {
                                                                        session->payloads[session->payload_len].name = apr_pstrdup(session->pool, name);
                                                                        session->payloads[session->payload_len].id = atoi(id);
@@ -317,10 +322,15 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
                                        }
                                        tag = iks_next_tag(tag);
                                }
-                       } else if (!strcasecmp(type, "candidates")) {
+                       } else if (!strcasecmp(type, "transport-info")) {
+                               char *tid = iks_find_attrib(xml, "id");
                                signal = LDL_SIGNAL_CANDIDATES;
                                tag = iks_child (xml);
                                
+                               if (tag && !strcasecmp(iks_name(tag), "transport")) {
+                                       tag = iks_child(tag);
+                               }
+                               
                                while(tag) {
                                        if (!strcasecmp(iks_name(tag), "info_element")) {
                                                char *name = iks_find_attrib(tag, "name");
@@ -354,6 +364,11 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
                                                }
                                                
                                                session->candidates[index].pref = pref;
+
+                                               if (tid) {
+                                                       session->candidates[index].tid = apr_pstrdup(session->pool, tid);
+                                               }
+
                                                if ((key = iks_find_attrib(tag, "name"))) {
                                                        session->candidates[index].name = apr_pstrdup(session->pool, key);
                                                }
@@ -427,8 +442,8 @@ static int on_presence(void *user_data, ikspak *pak)
        struct ldl_buffer *buffer;
        size_t x;
 
-       iks *msg = iks_make_s10n (IKS_TYPE_SUBSCRIBED, from, "Ding A Ling...."); 
-       apr_queue_push(handle->queue, msg);
+       //iks *msg = iks_make_s10n (IKS_TYPE_SUBSCRIBED, from, "Ding A Ling...."); 
+       //apr_queue_push(handle->queue, msg);
 
 
        apr_cpystrn(id, from, sizeof(id));
@@ -1087,6 +1102,31 @@ void *ldl_session_get_private(ldl_session_t *session)
        return session->private_data;
 }
 
+void ldl_session_accept_candidate(ldl_session_t *session, ldl_candidate_t *candidate)
+{
+       iks *iq, *sess, *tp;
+       unsigned int myid;
+    char idbuf[80];
+       myid = next_id();
+    snprintf(idbuf, sizeof(idbuf), "%u", myid);
+
+       iq = iks_new("iq");
+       iks_insert_attrib(iq, "type", "set");
+       iks_insert_attrib(iq, "id", idbuf);
+       iks_insert_attrib(iq, "from", session->handle->login);
+       iks_insert_attrib(iq, "to", session->them);
+       sess = iks_insert (iq, "session");
+    iks_insert_attrib(sess, "xmlns", "http://www.google.com/session");
+       iks_insert_attrib(sess, "type", "transport-accept");
+       iks_insert_attrib(sess, "id", candidate->tid);
+       iks_insert_attrib(sess, "xmlns", "http://www.google.com/session");
+       iks_insert_attrib(sess, "initiator", session->initiator ? session->initiator : session->them);
+       tp = iks_insert (sess, "transport");
+       iks_insert_attrib(tp, "xmlns", "http://www.google.com/transport/p2p");
+
+       apr_queue_push(session->handle->queue, iq);
+}
+
 void *ldl_handle_get_private(ldl_handle_t *handle)
 {
        return handle->private_info;
@@ -1128,18 +1168,27 @@ unsigned int ldl_session_terminate(ldl_session_t *session)
 
 }
 
+
 unsigned int ldl_session_candidates(ldl_session_t *session,
-                                                                 ldl_candidate_t *candidates,
-                                                                 unsigned int clen)
+                                                                       ldl_candidate_t *candidates,
+                                                                       unsigned int clen)
 
 {
        iks *iq, *sess, *tag;
        unsigned int x, id;
 
-       new_session_iq(session, &iq, &sess, &id, "candidates");
+
        for (x = 0; x < clen; x++) {
                char buf[512];
-               tag = iks_insert(sess, "candidate");
+               iq = NULL;
+               sess = NULL;
+               id = 0;
+
+               new_session_iq(session, &iq, &sess, &id, "transport-info");
+               tag = iks_insert(sess, "transport");
+               iks_insert_attrib(tag, "xmlns", "http://www.google.com/transport/p2p");
+               tag = iks_insert(tag, "candidate");
+
                if (candidates[x].name) {
                        iks_insert_attrib(tag, "name", candidates[x].name);
                }
@@ -1169,13 +1218,13 @@ unsigned int ldl_session_candidates(ldl_session_t *session,
 
                iks_insert_attrib(tag, "network", "0");
                iks_insert_attrib(tag, "generation", "0");
+               schedule_packet(session->handle, id, iq, LDL_RETRY);
        }
-       schedule_packet(session->handle, id, iq, LDL_RETRY);
+
 
        return id;
 }
 
-
 char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *buf, unsigned int len)
 {
        iks *pres, *msg;
@@ -1232,13 +1281,14 @@ unsigned int ldl_session_describe(ldl_session_t *session,
                                                                unsigned int plen,
                                                                ldl_description_t description)
 {
-       iks *iq, *sess, *tag, *payload;
+       iks *iq, *sess, *tag, *payload, *tp;
        unsigned int x, id;
        
 
        new_session_iq(session, &iq, &sess, &id, description == LDL_DESCRIPTION_ACCEPT ? "accept" : "initiate");
        tag = iks_insert(sess, "description");
        iks_insert_attrib(tag, "xmlns", "http://www.google.com/session/phone");
+       iks_insert_attrib(tag, "xml:lang", "en");
        for (x = 0; x < plen; x++) {
                char idbuf[80];
                payload = iks_insert(tag, "payload-type");
@@ -1249,10 +1299,19 @@ unsigned int ldl_session_describe(ldl_session_t *session,
                iks_insert_attrib(payload, "name", payloads[x].name);
                if (payloads[x].rate) {
                        sprintf(idbuf, "%d", payloads[x].rate);
-                       iks_insert_attrib(payload, "rate", idbuf);
+                       iks_insert_attrib(payload, "clockrate", idbuf);
+               }
+               if (payloads[x].bps) {
+                       sprintf(idbuf, "%d", payloads[x].bps);
+                       iks_insert_attrib(payload, "bitrate", idbuf);
                }
        }
 
+       if (description == LDL_DESCRIPTION_INITIATE) {
+               tp = iks_insert (sess, "transport");
+               iks_insert_attrib(tp, "xmlns", "http://www.google.com/transport/p2p");
+       }
+       
        schedule_packet(session->handle, id, iq, LDL_RETRY);
 
        return id;
index 2261cabb4f06c307f7db9d075d32dd774020034c..7c925c371e1b5f4e4d33cd38a4d747d0f2f0ad03 100644 (file)
@@ -53,6 +53,8 @@ extern "C" {
 
 /*! \brief A structure to store a jingle candidate */
 struct ldl_candidate {
+       /*! the transport id of the candidate */
+       char *tid;
        /*! the name of the candidate */
        char *name;
        /*! the type of the candidate */
@@ -80,6 +82,8 @@ struct ldl_payload {
        unsigned int id;
        /*! the transfer rate of the payload type */
        unsigned int rate;
+       /*! the bits per second of the payload type */
+       unsigned int bps;
 };
 typedef struct ldl_payload ldl_payload_t;
 
@@ -286,6 +290,13 @@ void ldl_session_set_private(ldl_session_t *session, void *private_data);
 */
 void *ldl_session_get_private(ldl_session_t *session);
 
+/*!
+  \brief Accept a candidate
+  \param session the session to accept on
+  \param candidate the candidate to accept
+*/
+void ldl_session_accept_candidate(ldl_session_t *session, ldl_candidate_t *candidate);
+
 /*!
   \brief Set a custom logger
   \param logger the logger function
@@ -316,6 +327,14 @@ unsigned int ldl_session_terminate(ldl_session_t *session);
 */
 void *ldl_handle_get_private(ldl_handle_t *handle);
 
+/*!
+  \brief Send a message to a session
+  \param session the session handle
+  \param to the message recipiant
+  \param subject optional subject
+  \param body body of the message
+*/
+void ldl_session_send_msg(ldl_session_t *session, char *subject, char *body);
 
 /*!
   \brief Send a message
index 5639ca07688c3235a8b01aa7b094cca65993213d..b8df0906fb3d40a4b07cdc502b4901190baff479 100644 (file)
@@ -443,6 +443,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_receive_message(switch_core_
 */
 SWITCH_DECLARE(switch_status_t) switch_core_session_queue_event(switch_core_session_t *session, switch_event_t **event);
 
+
+/*! 
+  \brief Indicate the number of waiting events on a session
+  \param session the session to check
+  \return the number of events
+*/
+SWITCH_DECLARE(int32_t) switch_core_session_event_count(switch_core_session_t *session);
+
 /*! 
   \brief DE-Queue an event on a given session
   \param session the session to de-queue the message on
index cd9678418f42b8db0ce4175b94215940a3b79e04..a5a386cca4c28664381b8bb42f9f08c66e1166cc 100644 (file)
@@ -155,6 +155,13 @@ SWITCH_DECLARE(switch_status_t) switch_event_set_priority(switch_event_t *event,
 */
 SWITCH_DECLARE(char *) switch_event_get_header(switch_event_t *event, char *header_name);
 
+/*!
+  \brief Retrieve the body value from an event
+  \param event the event to read the body from
+  \return the value of the body or NULL
+*/
+SWITCH_DECLARE(char *) switch_event_get_body(switch_event_t *event);
+
 /*!
   \brief Add a header to an event
   \param event the event to add the header to
index 42ad6d5f83bb5f59280928d30c5f216483ab2792..815c1af298341c5bc081f511410ca6b3b21152f0 100644 (file)
@@ -271,7 +271,7 @@ static const switch_codec_implementation_t speex_32k_implementation = {
        /*.ianacode */ 102,
        /*.iananame */ "speex",
        /*.samples_per_second */ 32000,
-       /*.bits_per_second */ 512000,
+       /*.bits_per_second */ 256000,
        /*.nanoseconds_per_frame */ 20000,
        /*.samples_per_frame */ 640,
        /*.bytes_per_frame */ 1280,
@@ -289,8 +289,8 @@ static const switch_codec_implementation_t speex_16k_implementation = {
        /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
        /*.ianacode */ 100,
        /*.iananame */ "speex",
-       /*.samples_per_second */ 16000,
-       /*.bits_per_second */ 256000,
+       /*.samples_per_second */ 22000,
+       /*.bits_per_second */ 128000,
        /*.nanoseconds_per_frame */ 20000,
        /*.samples_per_frame */ 320,
        /*.bytes_per_frame */ 640,
@@ -310,11 +310,11 @@ static const switch_codec_implementation_t speex_8k_implementation = {
        /*.ianacode */ 97,
        /*.iananame */ "speex",
        /*.samples_per_second */ 8000,
-       /*.bits_per_second */ 128000,
+       /*.bits_per_second */ 11000,
        /*.nanoseconds_per_frame */ 20000,
        /*.samples_per_frame */ 160,
        /*.bytes_per_frame */ 320,
-       /*.encoded_bytes_per_frame */ 0,
+       /*.encoded_bytes_per_frame */ 28,
        /*.number_of_channels */ 1,
        /*.pref_frames_per_packet */ 1,
        /*.max_frames_per_packet */ 1,
index fa2bb2f3844246bbc26d158e56c5a44d5b20d6ff..14b5b6d077a83a3924b4e27eb8c5d0ce26aa8081 100644 (file)
@@ -134,6 +134,7 @@ struct private_object {
        uint32_t last_read;
        char *codec_name;
        switch_payload_t codec_num;
+       switch_payload_t r_codec_num;
        switch_time_t next_desc;
        switch_time_t next_cand;
        char *stun_ip;
@@ -244,7 +245,7 @@ static int activate_rtp(struct private_object *tech_pvt)
        switch_rtp_flag_t flags;
 
        if (tech_pvt->rtp_session) {
-               return 0;
+               return 1;
        }
 
        if (!strncasecmp(tech_pvt->codec_name, "ilbc", 4)) {
@@ -260,7 +261,7 @@ static int activate_rtp(struct private_object *tech_pvt)
                                   NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Can't load codec?\n");
                switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
-               return -1;
+               return 0;
        }
        tech_pvt->read_frame.rate = tech_pvt->read_codec.implementation->samples_per_second;
        tech_pvt->read_frame.codec = &tech_pvt->read_codec;
@@ -276,7 +277,7 @@ static int activate_rtp(struct private_object *tech_pvt)
                                   NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Can't load codec?\n");
                switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
-               return -1;
+               return 0;
        }
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set Write Codec to %s\n",  tech_pvt->codec_name);
                                                        
@@ -287,6 +288,7 @@ static int activate_rtp(struct private_object *tech_pvt)
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SETUP RTP %s:%d -> %s:%d\n", tech_pvt->profile->ip, tech_pvt->local_port, tech_pvt->remote_ip, tech_pvt->remote_port);
        
        flags = SWITCH_RTP_FLAG_GOOGLEHACK | SWITCH_RTP_FLAG_AUTOADJ;
+       //flags = SWITCH_RTP_FLAG_AUTOADJ;
 
        if (switch_test_flag(tech_pvt->profile, TFLAG_TIMER)) {
          flags |= SWITCH_RTP_FLAG_USE_TIMER;
@@ -304,7 +306,7 @@ static int activate_rtp(struct private_object *tech_pvt)
                                                                                                 &err, switch_core_session_get_pool(tech_pvt->session)))) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RTP ERROR %s\n", err);
                switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
-               return -1;
+               return 0;
        } else {
                uint8_t vad_in = switch_test_flag(tech_pvt, TFLAG_VAD_IN) ? 1 : 0;
                uint8_t vad_out = switch_test_flag(tech_pvt, TFLAG_VAD_OUT) ? 1 : 0;
@@ -316,7 +318,7 @@ static int activate_rtp(struct private_object *tech_pvt)
                }
        }
 
-       return 0;
+       return 1;
 }
 
 
@@ -444,18 +446,23 @@ static int do_describe(struct private_object *tech_pvt, int force)
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Don't have my codec yet here's one\n");
                        tech_pvt->codec_name = lame(tech_pvt->codecs[0]->iananame);
                        tech_pvt->codec_num = tech_pvt->codecs[0]->ianacode;
+                       tech_pvt->r_codec_num = tech_pvt->codecs[0]->ianacode;
                        tech_pvt->codec_index = 0;
                                        
                        payloads[0].name = lame(tech_pvt->codecs[0]->iananame);
                        payloads[0].id = tech_pvt->codecs[0]->ianacode;
+                       payloads[0].rate = tech_pvt->codecs[0]->samples_per_second;
+                       payloads[0].bps = tech_pvt->codecs[0]->bits_per_second;
                        
                } else {
                        payloads[0].name = lame(tech_pvt->codecs[tech_pvt->codec_index]->iananame);
                        payloads[0].id = tech_pvt->codecs[tech_pvt->codec_index]->ianacode;
+                       payloads[0].rate = tech_pvt->codecs[0]->samples_per_second;
+                       payloads[0].bps = tech_pvt->codecs[0]->bits_per_second;
                }
 
                                
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send Describe [%s]\n", payloads[0].name);
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send Describe [%s@%d]\n", payloads[0].name, payloads[0].rate);
                tech_pvt->desc_id = ldl_session_describe(tech_pvt->dlsession, payloads, 1,
                                                                                                 switch_test_flag(tech_pvt, TFLAG_OUTBOUND) ? LDL_DESCRIPTION_INITIATE : LDL_DESCRIPTION_ACCEPT);
                switch_set_flag_locked(tech_pvt, TFLAG_CODEC_READY);
@@ -499,7 +506,7 @@ static void *SWITCH_THREAD_FUNC negotiate_thread_run(switch_thread_t *thread, vo
                elapsed = (unsigned int)((now - started) / 1000);
 
                if (switch_channel_get_state(channel) >= CS_HANGUP || switch_test_flag(tech_pvt, TFLAG_BYE)) {
-                       return NULL;
+                       goto out;
                }
 
                
@@ -528,10 +535,12 @@ static void *SWITCH_THREAD_FUNC negotiate_thread_run(switch_thread_t *thread, vo
        }
        
        if (switch_channel_get_state(channel) >= CS_HANGUP || switch_test_flag(tech_pvt, TFLAG_BYE)) {
-               return NULL;
+               goto out;
        }       
 
-       activate_rtp(tech_pvt);
+       if (!activate_rtp(tech_pvt)) {
+               goto out;
+       }
        
        if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
                do_candidates(tech_pvt, 0);
@@ -542,6 +551,13 @@ static void *SWITCH_THREAD_FUNC negotiate_thread_run(switch_thread_t *thread, vo
        }
        switch_channel_set_state(channel, CS_INIT);
        return NULL;
+       
+ out:
+       if (!switch_core_session_runing(tech_pvt->session)) {
+               channel_on_hangup(tech_pvt->session);
+               switch_core_session_destroy(&tech_pvt->session);
+       }
+       return NULL;
 }
 
 
@@ -920,6 +936,33 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
 
        return SWITCH_STATUS_SUCCESS;
 }
+
+static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event)
+{
+       switch_channel_t *channel;
+    struct private_object *tech_pvt;
+       char *subject, *body;
+
+    channel = switch_core_session_get_channel(session);
+    assert(channel != NULL);
+
+    tech_pvt = switch_core_session_get_private(session);
+    assert(tech_pvt != NULL);
+
+
+       if (!(body = switch_event_get_body(event))) {
+               body = "";
+       }
+
+       if (!(subject = switch_event_get_header(event, "subject"))) {
+               subject = "None";
+       }
+
+       ldl_session_send_msg(tech_pvt->dlsession, subject, body);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
 static const switch_state_handler_table_t channel_event_handlers = {
        /*.on_init */ channel_on_init,
        /*.on_ring */ channel_on_ring,
@@ -938,7 +981,8 @@ static const switch_io_routines_t channel_io_routines = {
        /*.waitfor_read */ channel_waitfor_read,
        /*.waitfor_write */ channel_waitfor_write,
        /*.send_dtmf */ channel_send_dtmf,
-       /*.receive_message*/ channel_receive_message
+       /*.receive_message*/ channel_receive_message,
+       /*.receive_event*/ channel_receive_event
 };
 
 static const switch_endpoint_interface_t channel_endpoint_interface = {
@@ -1531,7 +1575,9 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
                        if (*msg == '+') {
                                switch_channel_queue_dtmf(channel, msg + 1);
                                switch_set_flag_locked(tech_pvt, TFLAG_DTMF);
-                               switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_BREAK);
+                               if (tech_pvt->rtp_session) {
+                                       switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_BREAK);
+                               }
                        }
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "SESSION MSG [%s]\n", msg);
                }
@@ -1594,11 +1640,12 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
                                                        match = (payloads[x].id == tech_pvt->codecs[y]->ianacode) ? 1 : 0;
                                                }
                                                
-                                               if (match) {
+                                               if (match && payloads[x].rate == tech_pvt->codecs[y]->samples_per_second) {
                                                        tech_pvt->codec_index = y;
                                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Choosing Payload index %u %s %u\n", y, payloads[x].name, payloads[x].id);
                                                        tech_pvt->codec_name = tech_pvt->codecs[y]->iananame;
                                                        tech_pvt->codec_num = tech_pvt->codecs[y]->ianacode;
+                                                       tech_pvt->r_codec_num = payloads[x].id;
                                                        if (!switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
                                                                do_describe(tech_pvt, 0);
                                                        }
@@ -1663,7 +1710,9 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
 
                                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Acceptable Candidate %s:%d\n", candidates[x].address, candidates[x].port);
 
-
+                                               if (!switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
+                                                       ldl_session_accept_candidate(dlsession, &candidates[x]);
+                                               }
 
                                                if (!(exten = ldl_session_get_value(dlsession, "dnis"))) {
                                                        exten = profile->exten;
@@ -1719,10 +1768,13 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
                                                ldl_session_set_ip(dlsession, tech_pvt->remote_ip);
                                                tech_pvt->remote_port = candidates[x].port;
                                                tech_pvt->remote_user = switch_core_session_strdup(session, candidates[x].username);
+
                                                
                                                if (!switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
                                                        do_candidates(tech_pvt, 0);
                                                }
+                               
+                                               
                                                switch_set_flag_locked(tech_pvt, TFLAG_TRANSPORT);
                                                
                                                return LDL_STATUS_SUCCESS;
index 72acdea955b2efb8aa1efced048c5e7e7786b991..6836691a6a883360fea6b6141db1410027840635 100644 (file)
@@ -149,6 +149,262 @@ struct db_obj {
 };
 
 
+/* Event Object */
+/*********************************************************************************/
+static JSBool event_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       if (argc > 0) {
+               switch_event_t *event;
+               switch_event_types_t etype;
+               char *ename = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
+
+               if (switch_name_event(ename, &etype) != SWITCH_STATUS_SUCCESS) {
+                       *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+                       return JS_TRUE;
+               }
+
+               if (etype == SWITCH_EVENT_CUSTOM) {
+                       char *subclass_name;
+                       if (argc < 1) {
+                               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+                               return JS_TRUE;
+                       }
+                       
+                       subclass_name = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
+                       if (switch_event_create_subclass(&event, etype, subclass_name) != SWITCH_STATUS_SUCCESS) {
+                               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+                               return JS_TRUE;
+                       }
+
+               } else {
+                       if (!switch_event_create(&event, etype) != SWITCH_STATUS_SUCCESS) {
+                               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+                               return JS_TRUE;
+                       }
+               }
+
+               JS_SetPrivate(cx, obj, event);
+               return JS_TRUE;
+       }
+
+       return JS_FALSE;
+}
+
+static void event_destroy(JSContext *cx, JSObject *obj)
+{
+       switch_event_t *event = JS_GetPrivate(cx, obj);
+
+       if (event) {
+               switch_event_destroy(&event);
+       }
+}
+
+static JSBool event_add_header(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       switch_event_t *event = JS_GetPrivate(cx, obj);
+
+       if (!event) {
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
+       if (argc > 1) {
+               char *hname = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
+               char *hval = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
+               switch_event_add_header(event, SWITCH_STACK_BOTTOM, hname, hval);
+               *rval = BOOLEAN_TO_JSVAL( JS_TRUE );
+               return JS_TRUE;
+       }
+
+       *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+       return JS_TRUE;
+}
+
+static JSBool event_get_header(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       switch_event_t *event = JS_GetPrivate(cx, obj);
+
+       if (!event) {
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
+       if (argc > 0) {
+               char *hname = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
+               char *val = switch_event_get_header(event, hname);
+               *rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, val));
+               return JS_TRUE;
+       }
+
+       *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+       return JS_TRUE;
+}
+
+static JSBool event_add_body(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       switch_event_t *event = JS_GetPrivate(cx, obj);
+
+       if (!event) {
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
+       if (argc > 0) {
+               char *body = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
+               switch_event_add_body(event, body);
+               *rval = BOOLEAN_TO_JSVAL( JS_TRUE );
+               return JS_TRUE;
+       }
+
+       *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+       return JS_TRUE;
+}
+
+static JSBool event_get_body(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       switch_event_t *event = JS_GetPrivate(cx, obj);
+
+       if (!event) {
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
+       *rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, switch_event_get_body(event)));
+
+       return JS_TRUE;
+}
+
+static JSBool event_serialize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       switch_event_t *event = JS_GetPrivate(cx, obj);
+       char buf[1024];
+       uint8_t isxml = 0;
+
+       if (!event) {
+               *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+       }
+
+       if (argc > 0) {
+               char *arg = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
+               if (!strcasecmp(arg, "xml")) {
+                       isxml++;
+               }
+       }
+
+       if (isxml) {
+               switch_xml_t xml;
+               char *xmlstr;
+               if ((xml = switch_event_xmlize(event, NULL))) {
+            xmlstr = switch_xml_toxml(xml);
+                       *rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, xmlstr));
+                       switch_xml_free(xml);
+            free(xmlstr);
+               } else {
+                       *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+               }
+       } else {
+               switch_event_serialize(event, buf, sizeof(buf), NULL);
+               *rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, buf));
+       }
+
+       return JS_TRUE;
+}
+
+static JSBool event_fire(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       switch_event_t *event = JS_GetPrivate(cx, obj);
+
+       if (event) {
+               switch_event_fire(&event);
+               JS_SetPrivate(cx, obj, NULL);
+               *rval = BOOLEAN_TO_JSVAL( JS_TRUE );
+               return JS_TRUE;
+       }
+
+       *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+       return JS_TRUE;
+}
+
+static JSBool event_destroy_(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       switch_event_t *event = JS_GetPrivate(cx, obj);
+
+       if (event) {
+               switch_event_destroy(&event);
+               JS_SetPrivate(cx, obj, NULL);
+               *rval = BOOLEAN_TO_JSVAL( JS_TRUE );
+               return JS_TRUE;
+       }
+
+       *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+       return JS_TRUE;
+}
+
+
+
+enum event_tinyid {
+       EVENT_READY
+};
+
+static JSFunctionSpec event_methods[] = {
+       {"addHeader", event_add_header, 1},
+       {"getHeader", event_get_header, 1},
+       {"addBody", event_add_body, 1},
+       {"getBody", event_get_body, 1},
+       {"serialize", event_serialize, 0},
+       {"fire", event_fire, 0},
+       {"destroy", event_destroy_, 0},
+       {0}
+};
+
+
+static JSPropertySpec event_props[] = {
+       {"ready", EVENT_READY, JSPROP_READONLY|JSPROP_PERMANENT}, 
+       {0}
+};
+
+
+static JSBool event_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+       JSBool res = JS_TRUE;
+       switch_event_t *event = JS_GetPrivate(cx, obj);
+       char *name;
+       int param = 0;
+
+    if (!event) {
+        *vp = BOOLEAN_TO_JSVAL( JS_FALSE );
+               return JS_TRUE;
+    }
+
+       
+       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 EVENT_READY:
+               *vp = BOOLEAN_TO_JSVAL( JS_TRUE );
+               break;
+       }
+
+       return res;
+}
+
+JSClass event_class = {
+       "Event", JSCLASS_HAS_PRIVATE, 
+       JS_PropertyStub,  JS_PropertyStub,      event_getProperty,  JS_PropertyStub, 
+       JS_EnumerateStub, JS_ResolveStub,       JS_ConvertStub,   event_destroy, NULL, NULL, NULL,
+       event_construct
+};
+
+
+
+
 static void js_error(JSContext *cx, const char *message, JSErrorReport *report)
 {
        if (message) {
@@ -681,6 +937,52 @@ static JSBool session_execute(JSContext *cx, JSObject *obj, uintN argc, jsval *a
        return JS_TRUE;
 }
 
+static JSBool session_get_event(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       struct js_session *jss = JS_GetPrivate(cx, obj);
+       switch_event_t *event;
+
+       if (switch_core_session_dequeue_event(jss->session, &event) == SWITCH_STATUS_SUCCESS) {
+               JSObject *Event;
+               if ((Event = JS_DefineObject(cx, obj, "Event", &event_class, NULL, 0))) {
+                       if ((JS_SetPrivate(cx, Event, event) &&
+                                JS_DefineProperties(cx, Event, event_props) &&
+                                JS_DefineFunctions(cx, Event, event_methods))) {
+                               *rval = OBJECT_TO_JSVAL ( Event );
+                               return JS_TRUE;
+                       }
+               }
+       }
+       
+       *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+    return JS_TRUE;
+       
+}
+
+static JSBool session_send_event(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+       struct js_session *jss = JS_GetPrivate(cx, obj);
+       switch_event_t *event;
+       JSObject *Event;
+
+       if (argc > 0) {
+               if (JS_ValueToObject(cx, argv[0], &Event)) {
+                       if ((event = JS_GetPrivate(cx, Event))) {
+                               if (switch_core_session_receive_event(jss->session, &event) != SWITCH_STATUS_SUCCESS) {
+                                       *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+                                       return JS_TRUE;
+                               }
+
+                               JS_SetPrivate(cx, Event, NULL);
+                       }
+               }
+       }
+
+       *rval = BOOLEAN_TO_JSVAL( JS_TRUE );
+    return JS_TRUE;
+       
+}
+
 
 static JSBool session_hangup(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
@@ -845,6 +1147,7 @@ static JSBool js_fetchurl_file(JSContext *cx, JSObject *obj, uintN argc, jsval *
 }
 #endif
 
+
 /* Session Object */
 /*********************************************************************************/
 enum session_tinyid {
@@ -860,6 +1163,8 @@ static JSFunctionSpec session_methods[] = {
        {"answer", session_answer, 0}, 
        {"ready", session_ready, 0}, 
        {"waitForAnswer", session_wait_for_answer, 0}, 
+       {"getEvent", session_get_event, 0},
+       {"sendEvent", session_send_event, 0},
        {"hangup", session_hangup, 0}, 
        {"execute", session_execute, 0}, 
        {0}
@@ -2126,6 +2431,18 @@ static int env_init(JSContext *cx, JSObject *javascript_object)
                                 db_methods
                                 );
 
+       JS_InitClass(cx,
+                                javascript_object,
+                                NULL,
+                                &event_class,
+                                event_construct,
+                                3,
+                                event_props,
+                                event_methods,
+                                event_props,
+                                event_methods
+                                );
+
        return 1;
 }
 
index b23d0681ea4190aa729e79c931b841f2ed5ce5e2..6f9a1be7a9975a2ea61f15d1ea5299fe7de52d99 100644 (file)
@@ -1174,6 +1174,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_queue_event(switch_core_sess
        return status;
 }
 
+SWITCH_DECLARE(int32_t) switch_core_session_event_count(switch_core_session_t *session)
+{
+       if (session->event_queue) {
+               return (int32_t) switch_queue_size(session->event_queue);
+       }
+
+       return -1;
+}
+
 SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_event(switch_core_session_t *session, switch_event_t **event)
         
 {
index 9db2fc9f0c061836cf7ea376e545109eaa57f76c..dc09b1ae66a5b70ab72c54221abdb77df31887ea 100644 (file)
@@ -393,6 +393,15 @@ SWITCH_DECLARE(char *) switch_event_get_header(switch_event_t *event, char *head
        return NULL;
 }
 
+SWITCH_DECLARE(char *) switch_event_get_body(switch_event_t *event)
+{
+       if (event) {
+               return event->body;
+       }
+
+       return NULL;
+}
+
 SWITCH_DECLARE(switch_status_t) switch_event_add_header(switch_event_t *event, switch_stack_t stack, char *header_name,
                                                                                                          char *fmt, ...)
 {
@@ -623,7 +632,7 @@ SWITCH_DECLARE(switch_xml_t) switch_event_xmlize(switch_event_t *event, char *fm
                        switch_xml_t xbody = NULL;
 
                        add_xml_header(xml, "Content-Length", blena, off++);
-                       if ((xbody = switch_xml_add_child_d(xml, "body", 0))) {
+                       if ((xbody = switch_xml_add_child_d(xml, "body", off++))) {
                                switch_xml_set_txt_d(xbody, body);
                        }
                }
index f18a55d28a142a3b1aac4485483ad6994392bd9a..ae3c53f118a8fd427ce6a693961289e5bc36b644 100644 (file)
@@ -1012,7 +1012,7 @@ static char *switch_xml_toxml_r(switch_xml_t xml, char **s, switch_size_t *len,
     char *txt = (xml->parent) ? xml->parent->txt : "";
     switch_size_t off = 0;
        uint32_t lcount = 0;
-
+       
     // parent character content up to this tag
     *s = switch_xml_ampencode(txt + start, xml->off - start, s, len, max, 0);
 
@@ -1045,11 +1045,13 @@ static char *switch_xml_toxml_r(switch_xml_t xml, char **s, switch_size_t *len,
         switch_xml_ampencode(attr[i][j + 1], 0, s, len, max, 1);
         *len += sprintf(*s + *len, "\"");
     }
-    *len += sprintf(*s + *len, xml->child ? ">\n" : "/>\n");
+
+    *len += sprintf(*s + *len, (xml->child || xml->txt) ? ">" : "/>\n");
 
        if (xml->child) {
                (*count)++;
                *s = switch_xml_toxml_r(xml->child, s, len, max, 0, attr, count);
+
        } else {
                *s = switch_xml_ampencode(xml->txt, 0, s, len, max, 0);  //data
        }
@@ -1058,10 +1060,10 @@ static char *switch_xml_toxml_r(switch_xml_t xml, char **s, switch_size_t *len,
         *s = realloc(*s, *max += SWITCH_XML_BUFSIZE);
 
 
-       if (xml->child) {
-               for (lcount = 0; lcount < *count; lcount++) {
-                       *len += sprintf(*s + *len, "%s", XML_INDENT); // indent
-               }
+       if (xml->child || xml->txt) {
+               //for (lcount = 0; lcount < *count; lcount++) {
+               //*len += sprintf(*s + *len, "%s", XML_INDENT); // indent
+               //}
                *len += sprintf(*s + (*len), "</%s>\n", xml->name); // close tag
        }