[Freeswitch-svn] [commit] r2323 - in freeswitch/trunk: libs/libdingaling/src src src/include src/mod/codecs/mod_speex src/mod/endpoints/mod_dingaling src/mod/languages/mod_spidermonkey

Freeswitch SVN anthm at freeswitch.org
Thu Aug 17 21:28:51 EDT 2006


Author: anthm
Date: Thu Aug 17 21:28:50 2006
New Revision: 2323

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

Log:
Upgrade Dingaling to meet new googletalk spec upgrade your client if you have issues.
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();
    }
}





Modified: freeswitch/trunk/libs/libdingaling/src/libdingaling.c
==============================================================================
--- freeswitch/trunk/libs/libdingaling/src/libdingaling.c	(original)
+++ freeswitch/trunk/libs/libdingaling/src/libdingaling.c	Thu Aug 17 21:28:50 2006
@@ -190,6 +190,11 @@
 	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 @@
 	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 @@
 							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 @@
 					}
 					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 @@
 						}
 						
 						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 @@
 	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 @@
 	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_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 @@
 
 		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 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 @@
 		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;

Modified: freeswitch/trunk/libs/libdingaling/src/libdingaling.h
==============================================================================
--- freeswitch/trunk/libs/libdingaling/src/libdingaling.h	(original)
+++ freeswitch/trunk/libs/libdingaling/src/libdingaling.h	Thu Aug 17 21:28:50 2006
@@ -53,6 +53,8 @@
 
 /*! \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 @@
 	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;
 
@@ -287,6 +291,13 @@
 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 @@
 */
 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

Modified: freeswitch/trunk/src/include/switch_core.h
==============================================================================
--- freeswitch/trunk/src/include/switch_core.h	(original)
+++ freeswitch/trunk/src/include/switch_core.h	Thu Aug 17 21:28:50 2006
@@ -443,6 +443,14 @@
 */
 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

Modified: freeswitch/trunk/src/include/switch_event.h
==============================================================================
--- freeswitch/trunk/src/include/switch_event.h	(original)
+++ freeswitch/trunk/src/include/switch_event.h	Thu Aug 17 21:28:50 2006
@@ -156,6 +156,13 @@
 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
   \param stack the stack sense (stack it on the top or on the bottom)

Modified: freeswitch/trunk/src/mod/codecs/mod_speex/mod_speex.c
==============================================================================
--- freeswitch/trunk/src/mod/codecs/mod_speex/mod_speex.c	(original)
+++ freeswitch/trunk/src/mod/codecs/mod_speex/mod_speex.c	Thu Aug 17 21:28:50 2006
@@ -271,7 +271,7 @@
 	/*.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 @@
 	/*.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 @@
 	/*.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,

Modified: freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c	Thu Aug 17 21:28:50 2006
@@ -134,6 +134,7 @@
 	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 @@
 	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 @@
 				   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 @@
 				   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 @@
 	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 @@
 												 &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 @@
 		}
 	}
 
-	return 0;
+	return 1;
 }
 
 
@@ -444,18 +446,23 @@
 			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 @@
 		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 @@
 	}
 	
 	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 @@
 	}
 	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 @@
 
 	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 @@
 	/*.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 @@
 			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 @@
 							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,8 +1710,10 @@
 
 						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 @@
 						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;

Modified: freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c	(original)
+++ freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c	Thu Aug 17 21:28:50 2006
@@ -149,6 +149,262 @@
 };
 
 
+/* 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,7 +937,53 @@
 	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)
 {
 	struct js_session *jss = JS_GetPrivate(cx, obj);
@@ -845,6 +1147,7 @@
 }
 #endif
 
+
 /* Session Object */
 /*********************************************************************************/
 enum session_tinyid {
@@ -860,6 +1163,8 @@
 	{"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}
@@ -2124,6 +2429,18 @@
 				 db_methods,
 				 db_props,
 				 db_methods
+				 );
+
+	JS_InitClass(cx,
+				 javascript_object,
+				 NULL,
+				 &event_class,
+				 event_construct,
+				 3,
+				 event_props,
+				 event_methods,
+				 event_props,
+				 event_methods
 				 );
 
 	return 1;

Modified: freeswitch/trunk/src/switch_core.c
==============================================================================
--- freeswitch/trunk/src/switch_core.c	(original)
+++ freeswitch/trunk/src/switch_core.c	Thu Aug 17 21:28:50 2006
@@ -1174,6 +1174,15 @@
 	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)
 	 
 {

Modified: freeswitch/trunk/src/switch_event.c
==============================================================================
--- freeswitch/trunk/src/switch_event.c	(original)
+++ freeswitch/trunk/src/switch_event.c	Thu Aug 17 21:28:50 2006
@@ -393,6 +393,15 @@
 	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_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);
 			}
 		}

Modified: freeswitch/trunk/src/switch_xml.c
==============================================================================
--- freeswitch/trunk/src/switch_xml.c	(original)
+++ freeswitch/trunk/src/switch_xml.c	Thu Aug 17 21:28:50 2006
@@ -1012,7 +1012,7 @@
     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 @@
         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 @@
         *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
 	}
 



More information about the Freeswitch-svn mailing list