[Freeswitch-svn] [commit] r4781 - in freeswitch/branches/mikej/sofiasip-upgrade: . libs/libdingaling/src src src/include src/mod/endpoints/mod_sofia src/mod/languages/mod_spidermonkey

Freeswitch SVN mikej at freeswitch.org
Wed Mar 28 13:40:14 EDT 2007


Author: mikej
Date: Wed Mar 28 13:40:13 2007
New Revision: 4781

Modified:
   freeswitch/branches/mikej/sofiasip-upgrade/Makefile.am
   freeswitch/branches/mikej/sofiasip-upgrade/libs/libdingaling/src/libdingaling.c
   freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_core.h
   freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_module_interfaces.h
   freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_types.h
   freeswitch/branches/mikej/sofiasip-upgrade/src/mod/endpoints/mod_sofia/mod_sofia.c
   freeswitch/branches/mikej/sofiasip-upgrade/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
   freeswitch/branches/mikej/sofiasip-upgrade/src/mod/languages/mod_spidermonkey/mod_spidermonkey.h
   freeswitch/branches/mikej/sofiasip-upgrade/src/switch_channel.c
   freeswitch/branches/mikej/sofiasip-upgrade/src/switch_core.c
   freeswitch/branches/mikej/sofiasip-upgrade/src/switch_ivr.c

Log:
merged changes from trunk revisions 4772-4780.

Modified: freeswitch/branches/mikej/sofiasip-upgrade/Makefile.am
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/Makefile.am	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/Makefile.am	Wed Mar 28 13:40:13 2007
@@ -221,3 +221,9 @@
 
 megaclean: eclean modclean
 	rm -f `find ./libs -name \*.la`
+
+
+# Special targets
+
+coffee me_a_sandwich me_a_sammich:
+	@echo "Who do you think I am?  Make it yourself!"

Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/libdingaling/src/libdingaling.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/libdingaling/src/libdingaling.c	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/libdingaling/src/libdingaling.c	Wed Mar 28 13:40:13 2007
@@ -1218,15 +1218,12 @@
 
 static void on_log(ldl_handle_t *handle, const char *data, size_t size, int is_incoming)
 {
-	if (iks_is_secure(handle->parser)) {
-		fprintf(stderr, "Sec");
+	if (globals.debug) {
+		globals.logger(DL_LOG_DEBUG, "\n%s%s[%s]\n", 
+			iks_is_secure(handle->parser) ? "Sec" : "",
+			is_incoming ? "RECV" : "SEND",
+			data);
 	}
-	if (is_incoming) {
-		fprintf(stderr, "RECV");
-	} else {
-		fprintf(stderr, "SEND");
-	}
-	fprintf(stderr, "[%s]\n", data);
 }
 
 static void j_setup_filter(ldl_handle_t *handle)
@@ -1423,16 +1420,18 @@
 			break;
 		case IKS_NET_NODNS:
 			globals.logger(DL_LOG_DEBUG, "hostname lookup failed\n");
+			microsleep(1000);
+			goto fail;
 		case IKS_NET_NOCONN:
 			globals.logger(DL_LOG_DEBUG, "connection failed\n");
+			microsleep(1000);
+			goto fail;
 		default:
-			globals.logger(DL_LOG_DEBUG, "io error %d\n", e);
-			microsleep(500);
-			continue;
+			globals.logger(DL_LOG_DEBUG, "io error 1 %d\n", e);
+			microsleep(1000);
+			goto fail;
 		}
 
-
-
 		handle->counter = opt_timeout;
 		if (ldl_test_flag(handle, LDL_FLAG_TLS)) {
 			launch_queue_thread(handle);
@@ -1456,9 +1455,9 @@
 			}
 
 			if (IKS_OK != e) {
-				globals.logger(DL_LOG_DEBUG, "io error %d\n", e);
-				microsleep(500);
-				break;
+				globals.logger(DL_LOG_DEBUG, "io error 2 %d\n", e);
+				microsleep(1000);
+				goto fail;
 			}
 
 			
@@ -1481,10 +1480,12 @@
 			}
 		}
 
+	fail:
 		iks_disconnect(handle->parser);
 		iks_parser_delete(handle->parser);
 		ldl_clear_flag_locked(handle, LDL_FLAG_CONNECTED);
 		ldl_clear_flag_locked(handle, LDL_FLAG_AUTHORIZED);
+		handle->state = CS_NEW;
 	}
 	ldl_clear_flag_locked(handle, LDL_FLAG_RUNNING);
 

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_core.h
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_core.h	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_core.h	Wed Mar 28 13:40:13 2007
@@ -856,6 +856,15 @@
   \return SWITCH_STATUS_SUCCESS on suceess
 */
 SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_send_dtmf(switch_core_session_t *session, switch_send_dtmf_hook_t send_dtmf);
+
+/*! 
+  \brief Add an event hook to be executed when a session receives a state change signal
+  \param session session to bind hook to
+  \param state_change hook to bind
+  \return SWITCH_STATUS_SUCCESS on suceess
+*/
+SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_state_change(switch_core_session_t *session,
+																				switch_answer_channel_hook_t state_change);
 ///\}
 
 ///\defgroup hashf Hash Functions

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_module_interfaces.h
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_module_interfaces.h	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_module_interfaces.h	Wed Mar 28 13:40:13 2007
@@ -145,6 +145,13 @@
 	struct switch_io_event_hook_send_dtmf *next;
 };
 
+/*! \brief Node in which to store state change callback hooks */
+struct switch_io_event_hook_state_change {
+	/*! the send dtmf channel callback hook*/
+	switch_state_change_hook_t state_change;
+	struct switch_io_event_hook_state_change *next;
+};
+
 /*! \brief A table of lists of io_event_hooks to store the event hooks associated with a session */
 struct switch_io_event_hooks {
 	/*! a list of outgoing channel hooks */
@@ -167,6 +174,8 @@
 	switch_io_event_hook_waitfor_write_t *waitfor_write;
 	/*! a list of send dtmf hooks */
 	switch_io_event_hook_send_dtmf_t *send_dtmf;
+	/*! a list of state change hooks */
+	switch_io_event_hook_state_change_t *state_change;
 };
 
 /*! \brief A table of i/o routines that an endpoint interface can implement */
@@ -191,6 +200,8 @@
 	switch_status_t (*receive_message)(switch_core_session_t *, switch_core_session_message_t *);
 	/*! queue a message for another session*/
 	switch_status_t (*receive_event)(switch_core_session_t *, switch_event_t *);
+	/*! change a sessions channel state */
+	switch_status_t (*state_change)(switch_core_session_t *);
 };
 
 /*! \brief Abstraction of an module endpoint interface

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_types.h
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_types.h	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_types.h	Wed Mar 28 13:40:13 2007
@@ -954,6 +954,7 @@
 typedef struct switch_io_event_hook_waitfor_read switch_io_event_hook_waitfor_read_t;
 typedef struct switch_io_event_hook_waitfor_write switch_io_event_hook_waitfor_write_t;
 typedef struct switch_io_event_hook_send_dtmf switch_io_event_hook_send_dtmf_t;
+typedef struct switch_io_event_hook_state_change switch_io_event_hook_state_change_t;
 typedef struct switch_io_routines switch_io_routines_t;
 typedef struct switch_io_event_hooks switch_io_event_hooks_t;
 typedef struct switch_speech_handle switch_speech_handle_t;
@@ -989,6 +990,7 @@
 typedef switch_status_t (*switch_waitfor_read_hook_t)(switch_core_session_t *, int, int);
 typedef switch_status_t (*switch_waitfor_write_hook_t)(switch_core_session_t *, int, int);
 typedef switch_status_t (*switch_send_dtmf_hook_t)(switch_core_session_t *, char *);
+typedef switch_status_t (*switch_state_change_hook_t)(switch_core_session_t *);
 typedef struct switch_stream_handle switch_stream_handle_t;
 typedef switch_status_t (*switch_stream_handle_write_function_t)(switch_stream_handle_t *handle, const char *fmt, ...);
 typedef switch_status_t (*switch_api_function_t)(char *in, switch_core_session_t *session, switch_stream_handle_t *stream);

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/mod/endpoints/mod_sofia/mod_sofia.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/mod/endpoints/mod_sofia/mod_sofia.c	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/mod/endpoints/mod_sofia/mod_sofia.c	Wed Mar 28 13:40:13 2007
@@ -2565,8 +2565,14 @@
 			for (map = m->m_rtpmaps; map; map = map->rm_next) {
 				int32_t i;
                 const switch_codec_implementation_t *mimp = NULL, *near_match = NULL;
+				const char * rm_encoding;
 
-				if (!te && !strcasecmp(map->rm_encoding, "telephone-event")) {
+				
+				if (!(rm_encoding = map->rm_encoding)) {
+					rm_encoding = "";
+				}
+				
+				if (!te && !strcasecmp(rm_encoding, "telephone-event")) {
 					te = tech_pvt->te = (switch_payload_t)map->rm_pt;
 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set 2833 dtmf payload to %u\n", te);
 					if (tech_pvt->rtp_session) {
@@ -2574,7 +2580,7 @@
 					}
 				}
 
-				if (!cng_pt && !strcasecmp(map->rm_encoding, "CN")) {
+				if (!cng_pt && !strcasecmp(rm_encoding, "CN")) {
 					cng_pt = tech_pvt->cng_pt = (switch_payload_t)map->rm_pt;
 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set comfort noise payload to %u\n", cng_pt);
 					if (tech_pvt->rtp_session) {
@@ -2593,11 +2599,11 @@
 				for (i = 0; i < tech_pvt->num_codecs; i++) {
 					const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Codec Compare [%s:%d]/[%s:%d]\n", 
-									  map->rm_encoding, map->rm_pt, imp->iananame, imp->ianacode);
+									  rm_encoding, map->rm_pt, imp->iananame, imp->ianacode);
 					if (map->rm_pt < 96) {
 						match = (map->rm_pt == imp->ianacode) ? 1 : 0;
 					} else {
-						match = strcasecmp(map->rm_encoding, imp->iananame) ? 0 : 1;
+						match = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1;
 					}
 
 					if (match && (map->rm_rate == imp->samples_per_second)) {
@@ -2639,7 +2645,7 @@
                 }
 
                 if (mimp) {
-                    if ((tech_pvt->rm_encoding = switch_core_session_strdup(session, (char *)map->rm_encoding))) {
+                    if ((tech_pvt->rm_encoding = switch_core_session_strdup(session, (char *)rm_encoding))) {
                         char tmp[50];
                         tech_pvt->pt = (switch_payload_t)map->rm_pt;
                         tech_pvt->rm_rate = map->rm_rate;

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c	Wed Mar 28 13:40:13 2007
@@ -43,6 +43,7 @@
 
 static void session_destroy(JSContext *cx, JSObject *obj);
 static JSBool session_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+static JSBool session_originate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
 static switch_api_interface_t js_run_interface;
 
 static struct {
@@ -79,7 +80,8 @@
 typedef struct sm_loadable_module sm_loadable_module_t;
 
 typedef enum {
-	S_HUP = (1 << 0)
+	S_HUP = (1 << 0),
+	S_FREE = (1 << 1)
 } session_flag_t;
 
 struct input_callback_state {
@@ -640,7 +642,8 @@
 	jsval argv[4];
 	JSObject *Event = NULL;
 
-	if (!jss) {
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
 		return SWITCH_STATUS_FALSE;
 	}
 
@@ -822,15 +825,15 @@
 	switch_size_t has;
 	switch_channel_t *channel;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
-    if (!switch_channel_ready(channel)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session is not active!\n");
-        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-        return JS_TRUE;
-    }
-
 	while ((has = switch_channel_has_dtmf(channel))) {
 		switch_channel_dequeue_dtmf(channel, buf, sizeof(buf));
 	}
@@ -845,14 +848,14 @@
 	switch_event_t *event;
     switch_channel_t *channel;
 
+	if (!jss || !jss->session) {
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
     channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
-    if (!switch_channel_ready(channel)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session is not active!\n");
-        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-        return JS_TRUE;
-    }
 
 	while (switch_core_session_dequeue_event(jss->session, &event) == SWITCH_STATUS_SUCCESS) {
 		switch_event_destroy(&event);
@@ -877,6 +880,12 @@
     int32 limit = 0;
     switch_input_args_t args = {0};
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -953,6 +962,13 @@
 	JSFunction *function;
     switch_input_args_t args = {0};
 
+
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1014,6 +1030,12 @@
 	JSFunction *function;
     switch_input_args_t args = {0};
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1074,6 +1096,55 @@
 	return JS_TRUE;
 }
 
+static void check_hangup_hook(struct js_session *jss)
+{
+	jsval argv[2] = {0};
+	int argc = 0;
+	jsval ret;
+	if (jss->on_hangup ) {
+		argv[argc++] = OBJECT_TO_JSVAL(jss->obj);			
+		JS_CallFunction(jss->cx, jss->obj, jss->on_hangup, argc, argv, &ret);
+	}
+}
+
+static switch_status_t hanguphook(switch_core_session_t *session)
+{
+	switch_channel_t *channel;
+	struct js_session *jss = NULL;
+
+	channel = switch_core_session_get_channel(session);
+	assert(channel != NULL);
+	if (switch_channel_get_state(channel) == CS_HANGUP) {
+		if ((jss = switch_channel_get_private(channel, "jss"))) {
+			check_hangup_hook(jss);
+		}
+	}
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static JSBool session_hanguphook(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+	JSFunction *function;
+	struct js_session *jss;
+	*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+
+	if ((jss = JS_GetPrivate(cx, obj)) && jss->session) {
+		if (argc > 0) {
+			if ((function = JS_ValueToFunction(cx, argv[0]))) {
+				switch_channel_t *channel = switch_core_session_get_channel(jss->session);
+				assert(channel != NULL);
+				jss->on_hangup = function;
+				switch_channel_set_private(channel, "jss", jss);
+				switch_core_session_add_event_hook_state_change(jss->session, hanguphook);
+				*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+			}
+		}
+	}
+
+	return JS_TRUE;
+}
+
 static JSBool session_streamfile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
 	struct js_session *jss = JS_GetPrivate(cx, obj);
@@ -1088,6 +1159,12 @@
 	JSFunction *function;
     switch_input_args_t args = {0};
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1147,16 +1224,15 @@
 	struct js_session *jss = JS_GetPrivate(cx, obj);
     switch_channel_t *channel;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
-    if (!switch_channel_ready(channel)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session is not active!\n");
-        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-        return JS_TRUE;
-    }
-
-
 	if (argc > 1) {
 		char *var, *val;
 
@@ -1176,16 +1252,14 @@
 	struct js_session *jss = JS_GetPrivate(cx, obj);
     switch_channel_t *channel;
 
+	if (!jss || !jss->session) {
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
-    if (!switch_channel_ready(channel)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session is not active!\n");
-        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-        return JS_TRUE;
-    }
-
-
 	if (argc > 0) {
 		char *var, *val;
 		
@@ -1220,6 +1294,12 @@
 	JSFunction *function;
     switch_input_args_t args = {0};
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1286,6 +1366,12 @@
 	int32 digits = 0, timeout = 5000;
 	switch_channel_t *channel;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
@@ -1321,11 +1407,42 @@
 	return JS_FALSE;
 }
 
+static JSBool session_autohangup(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+	struct js_session *jss = JS_GetPrivate(cx, obj);
+	*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
+
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+	
+	if (argv[0]) {
+		JSBool tf;
+		JS_ValueToBoolean(cx, argv[0], &tf);
+		if (tf == JS_TRUE) {
+			switch_set_flag(jss, S_HUP);
+		} else {
+			switch_clear_flag(jss, S_HUP);
+		}
+		*rval = BOOLEAN_TO_JSVAL(tf);
+	}
+
+	return JS_TRUE;
+}
+
 static JSBool session_answer(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
 	struct js_session *jss = JS_GetPrivate(cx, obj);
 	switch_channel_t *channel;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1349,6 +1466,11 @@
 	/*Always a pessimist... sheesh!*/
 	*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		return JS_TRUE;
+	}
+
     if (switch_ivr_generate_xml_cdr(jss->session, &cdr) == SWITCH_STATUS_SUCCESS) {
 		char *xml_text;
 		if ((xml_text = switch_xml_toxml(cdr))) {
@@ -1366,6 +1488,12 @@
 	struct js_session *jss = JS_GetPrivate(cx, obj);
 	switch_channel_t *channel;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1384,6 +1512,12 @@
 	unsigned int elapsed;
 	int32 timeout = 60;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1419,6 +1553,12 @@
 	unsigned int elapsed;
 	int32 timeout = 60;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1451,6 +1591,12 @@
 	switch_channel_t *channel;
     struct js_session *jss = JS_GetPrivate(cx, obj);
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
@@ -1468,6 +1614,12 @@
 		struct js_session *jss = JS_GetPrivate(cx, obj);
 		jsrefcount saveDepth;
 
+		if (!jss || !jss->session) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+			*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+			return JS_TRUE;
+		}
+
 		if ((application_interface = switch_loadable_module_get_application_interface(app_name))) {
 			if (application_interface->application_function) {
 				saveDepth = JS_SuspendRequest(cx);
@@ -1486,17 +1638,12 @@
 {
 	struct js_session *jss = JS_GetPrivate(cx, obj);
 	switch_event_t *event;
-	switch_channel_t *channel;
-
-	channel = switch_core_session_get_channel(jss->session);
-    assert(channel != NULL);
-
-    if (!switch_channel_ready(channel)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session is not active!\n");
-        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-        return JS_TRUE;
-    }
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
 
 	if (switch_core_session_dequeue_event(jss->session, &event) == SWITCH_STATUS_SUCCESS) {
 		JSObject *Event;
@@ -1528,6 +1675,12 @@
 	JSObject *Event;
 	struct event_obj *eo;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	if (argc > 0) {
 		if (JS_ValueToObject(cx, argv[0], &Event)) {
 			if ((eo = JS_GetPrivate(cx, Event))) {
@@ -1554,6 +1707,12 @@
 	char *cause_name = NULL;
 	switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1722,10 +1881,13 @@
 /*********************************************************************************/
 enum session_tinyid {
 	SESSION_NAME, SESSION_STATE,
-	PROFILE_DIALPLAN, PROFILE_CID_NAME, PROFILE_CID_NUM, PROFILE_IP, PROFILE_ANI, PROFILE_ANI_II, PROFILE_DEST, SESSION_UUID
+	PROFILE_DIALPLAN, PROFILE_CID_NAME, PROFILE_CID_NUM, PROFILE_IP, PROFILE_ANI, PROFILE_ANI_II, PROFILE_DEST, SESSION_UUID, SESSION_CAUSE
 };
 
 static JSFunctionSpec session_methods[] = {
+	{"originate", session_originate, 2}, 
+	{"setHangupHook", session_hanguphook, 1}, 
+	{"setAutoHangup", session_autohangup, 1}, 
     {"sayPhrase", session_sayphrase, 1}, 
     {"streamFile", session_streamfile, 1}, 
 	{"collectInput", session_collect_input, 1}, 
@@ -1760,6 +1922,7 @@
 	{"aniii", PROFILE_ANI_II, JSPROP_READONLY|JSPROP_PERMANENT}, 
 	{"destination", PROFILE_DEST, JSPROP_READONLY|JSPROP_PERMANENT}, 
 	{"uuid", SESSION_UUID, JSPROP_READONLY|JSPROP_PERMANENT}, 
+	{"cause", SESSION_CAUSE, JSPROP_READONLY|JSPROP_PERMANENT}, 
 	{0}
 };
 
@@ -1767,29 +1930,40 @@
 {
 	struct js_session *jss = JS_GetPrivate(cx, obj);
 	int param = 0;
-	JSBool res = JS_TRUE;
-	switch_channel_t *channel;
-	switch_caller_profile_t *caller_profile;
-	char *name;
-	
-	if (!jss || !jss->session) {
-		return JS_FALSE;
+	switch_channel_t *channel = NULL;
+	switch_caller_profile_t *caller_profile = NULL;
+	char *name = NULL;
+
+	if (jss && jss->session) {
+		channel = switch_core_session_get_channel(jss->session);
+		assert(channel != NULL);
+		caller_profile = switch_channel_get_caller_profile(channel);
 	}
 
-	channel = switch_core_session_get_channel(jss->session);
-	assert(channel != NULL);
-
-	caller_profile = switch_channel_get_caller_profile(channel);
-
 	name = JS_GetStringBytes(JS_ValueToString(cx, id));
+
 	/* numbers are our props anything else is a method */
 	if (name[0] >= 48 && name[0] <= 57) {
 		param = atoi(name);
 	} else {
 		return JS_TRUE;
 	}
-	
+
+	if (!channel) {
+		switch(param) {
+		case SESSION_CAUSE:
+			*vp = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, switch_channel_cause2str(jss->cause)));
+			break;
+		default:
+			*vp = BOOLEAN_TO_JSVAL(JS_FALSE);
+		}
+		return JS_TRUE;
+	}
+
 	switch(param) {
+	case SESSION_CAUSE:
+		*vp = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, switch_channel_cause2str(switch_channel_get_cause(channel))));
+		break;
 	case SESSION_NAME:
 		*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, switch_channel_get_name(channel)));
 		break;
@@ -1835,12 +2009,12 @@
 		}
 		break;
 	default:
-		res = JS_FALSE;
+		*vp = BOOLEAN_TO_JSVAL(JS_FALSE);
 		break;
-
+		
 	}
 
-	return res;
+	return JS_TRUE;
 }
 
 JSClass session_class = {
@@ -1859,7 +2033,7 @@
 		jss->session = session;
 		jss->flags = flags;
 		jss->cx = cx;
-		jss->obj = obj;
+		jss->obj = session_obj;
 		if ((JS_SetPrivate(cx, session_obj, jss) &&
 			 JS_DefineProperties(cx, session_obj, session_props) &&
 			 JS_DefineFunctions(cx, session_obj, session_methods))) {
@@ -1870,18 +2044,36 @@
 	return NULL;
 }
 
-
 /* Session Object */
 /*********************************************************************************/
+
 static JSBool session_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
+	struct js_session *jss = NULL;
+
+	assert((jss = malloc(sizeof(*jss))));
+	memset(jss, 0, sizeof(*jss));
+	jss->cx = cx;
+	jss->obj = obj;
+	switch_set_flag(jss, S_FREE);
+
+	JS_SetPrivate(cx, obj, jss);
+
+	return JS_TRUE;
+}
+
+static JSBool session_originate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+	struct js_session *jss = NULL;
 	switch_memory_pool_t *pool = NULL;
+
+	jss = JS_GetPrivate(cx, obj);
+	jss->cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+
 	if (argc > 1) {
-		switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
-		struct js_session *jss = NULL;
 		JSObject *session_obj;
 		switch_core_session_t *session = NULL, *peer_session = NULL;
-		switch_caller_profile_t *caller_profile = NULL;
+		switch_caller_profile_t *caller_profile = NULL, *orig_caller_profile = NULL;
 		char *dest = NULL;
 		char *dialplan = NULL;
 		char *cid_name = "";
@@ -1893,12 +2085,22 @@
 		char *context = "";
 		char *username = NULL;
 		char *to = NULL;
-		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+
+		*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
 
 		if (JS_ValueToObject(cx, argv[0], &session_obj)) {
 			struct js_session *old_jss = NULL;
 			if ((old_jss = JS_GetPrivate(cx, session_obj))) {
 				session = old_jss->session;
+				orig_caller_profile = switch_channel_get_caller_profile(switch_core_session_get_channel(session));
+				dialplan = orig_caller_profile->dialplan;
+				cid_name = orig_caller_profile->caller_id_name;
+				cid_num = orig_caller_profile->caller_id_number;
+				ani = orig_caller_profile->ani;
+				aniii = orig_caller_profile->aniii;
+				rdnis = orig_caller_profile->rdnis;
+				context = orig_caller_profile->context;
+				username = orig_caller_profile->username;
 			}
 		}
 
@@ -1906,7 +2108,7 @@
 
 		if (!strchr(dest, '/')) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid Channel String\n");
-			return JS_TRUE;
+			goto done;
 		}
 
 		if (argc > 2) {
@@ -1940,7 +2142,6 @@
 			to = JS_GetStringBytes(JS_ValueToString(cx, argv[11]));
 		}
 		
-		
 		if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
 			return JS_FALSE;
@@ -1959,41 +2160,45 @@
 												   context,
 												   dest);
 		
-		if (switch_ivr_originate(session, &peer_session, &cause, dest, to ? atoi(to) : 60, NULL, NULL, NULL, caller_profile) != SWITCH_STATUS_SUCCESS) {
+		if (switch_ivr_originate(session, &peer_session, &jss->cause, dest, to ? atoi(to) : 60, NULL, NULL, NULL, caller_profile) != SWITCH_STATUS_SUCCESS) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot Create Outgoing Channel! [%s]\n", dest);
-			return JS_TRUE;
+			goto done;
 		}
 
-		*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, switch_channel_cause2str(cause)));
-
-		jss = switch_core_session_alloc(peer_session, sizeof(*jss));
 		jss->session = peer_session;
 		jss->flags = 0;
-		jss->cx = cx;
-		jss->obj = obj;
-		JS_SetPrivate(cx, obj, jss);
-		switch_set_flag(jss, S_HUP);
+
+		*rval = BOOLEAN_TO_JSVAL(JS_TRUE);
 
 	} else {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing Args\n");
 	}
 
+ done:
 	return JS_TRUE;
 }
 
+
+
+
 static void session_destroy(JSContext *cx, JSObject *obj)
 {
 	struct js_session *jss;
+	switch_channel_t *channel = NULL;
 	
 	if (cx && obj) {
 		if ((jss = JS_GetPrivate(cx, obj))) {
-			if (switch_test_flag(jss, S_HUP)) {
-				switch_channel_t *channel;
+			if (jss->session) {
+				channel = switch_core_session_get_channel(jss->session);
+				switch_channel_set_private(channel, "jss", NULL);
+			}
 
-				if (jss->session) {
-					channel = switch_core_session_get_channel(jss->session);
-					switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
-				}
+			if (channel && switch_test_flag(jss, S_HUP)) {
+				switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+			}
+
+			if (switch_test_flag(jss, S_FREE)) {
+				free(jss);
 			}
 		}
 	}
@@ -2073,8 +2278,9 @@
 	switch_size_t read = 0;
 
 	*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-
-	if (fio) {
+	
+	if (!fio) {
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
 		return JS_TRUE;
 	}
 

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/mod/languages/mod_spidermonkey/mod_spidermonkey.h
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/mod/languages/mod_spidermonkey/mod_spidermonkey.h	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/mod/languages/mod_spidermonkey/mod_spidermonkey.h	Wed Mar 28 13:40:13 2007
@@ -132,6 +132,8 @@
 	JSContext *cx;
 	JSObject *obj;
 	unsigned int flags;
+	switch_call_cause_t cause;
+	JSFunction *on_hangup;
 };
 
 

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/switch_channel.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/switch_channel.c	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/switch_channel.c	Wed Mar 28 13:40:13 2007
@@ -948,11 +948,13 @@
 
 SWITCH_DECLARE(switch_caller_extension_t *) switch_channel_get_caller_extension(switch_channel_t *channel)
 {
-    switch_caller_extension_t *extension;
+    switch_caller_extension_t *extension = NULL;
 
 	assert(channel != NULL);
 	switch_mutex_lock(channel->profile_mutex);
-	extension = channel->caller_profile->caller_extension;
+	if (channel->caller_profile) {
+		extension = channel->caller_profile->caller_extension;
+	}
     switch_mutex_unlock(channel->profile_mutex);
     return extension;
 }

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/switch_core.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/switch_core.c	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/switch_core.c	Wed Mar 28 13:40:13 2007
@@ -185,7 +185,6 @@
 /* The main runtime obj we keep this hidden for ourselves */
 static struct switch_core_runtime runtime;
 
-
 static void db_pick_path(char *dbname, char *buf, switch_size_t size)
 {
 
@@ -1835,20 +1834,22 @@
 SWITCH_DECLARE(switch_status_t) switch_core_session_answer_channel(switch_core_session_t *session)
 {
 	switch_io_event_hook_answer_channel_t *ptr;
-	switch_status_t status = SWITCH_STATUS_FALSE;
+	switch_status_t status = SWITCH_STATUS_SUCCESS;
 
 	assert(session != NULL);
+
 	if (session->endpoint_interface->io_routines->answer_channel) {
-		if ((status = session->endpoint_interface->io_routines->answer_channel(session)) == SWITCH_STATUS_SUCCESS) {
-			for (ptr = session->event_hooks.answer_channel; ptr; ptr = ptr->next) {
-				if ((status = ptr->answer_channel(session)) != SWITCH_STATUS_SUCCESS) {
-					break;
-				}
+		status = session->endpoint_interface->io_routines->answer_channel(session);
+	}
+
+	if (status == SWITCH_STATUS_SUCCESS) {
+		for (ptr = session->event_hooks.answer_channel; ptr; ptr = ptr->next) {
+			if ((status = ptr->answer_channel(session)) != SWITCH_STATUS_SUCCESS) {
+				break;
 			}
 		}
-	} else {
-		status = SWITCH_STATUS_SUCCESS;
 	}
+	 
 
 	return status;
 }
@@ -1856,19 +1857,23 @@
 SWITCH_DECLARE(switch_status_t) switch_core_session_receive_message(switch_core_session_t *session, switch_core_session_message_t *message)
 {
 	switch_io_event_hook_receive_message_t *ptr;
-	switch_status_t status = SWITCH_STATUS_FALSE;
+	switch_status_t status = SWITCH_STATUS_SUCCESS;
 
 	assert(session != NULL);
+
 	if (session->endpoint_interface->io_routines->receive_message) {
-		if ((status =
-			 session->endpoint_interface->io_routines->receive_message(session, message)) == SWITCH_STATUS_SUCCESS) {
-			for (ptr = session->event_hooks.receive_message; ptr; ptr = ptr->next) {
-				if ((status = ptr->receive_message(session, message)) != SWITCH_STATUS_SUCCESS) {
-					break;
-				}
+		status = session->endpoint_interface->io_routines->receive_message(session, message);
+		
+	}
+
+	if (status == SWITCH_STATUS_SUCCESS) {
+		for (ptr = session->event_hooks.receive_message; ptr; ptr = ptr->next) {
+			if ((status = ptr->receive_message(session, message)) != SWITCH_STATUS_SUCCESS) {
+				break;
 			}
 		}
 	}
+
 	switch_core_session_kill_channel(session, SWITCH_SIG_BREAK);
 	return status;
 }
@@ -2874,6 +2879,31 @@
 
 }
 
+SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_state_change(switch_core_session_t *session,
+																				switch_answer_channel_hook_t state_change)
+																				  
+
+{
+	switch_io_event_hook_state_change_t *hook, *ptr;
+
+	assert(state_change != NULL);
+	if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
+		hook->state_change = state_change;
+		if (!session->event_hooks.state_change) {
+			session->event_hooks.state_change = hook;
+		} else {
+			for (ptr = session->event_hooks.state_change; ptr && ptr->next; ptr = ptr->next);
+			ptr->next = hook;
+
+		}
+
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	return SWITCH_STATUS_MEMERR;
+
+}
+
 SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_read_frame(switch_core_session_t *session,
 																			switch_read_frame_hook_t read_frame)
 {
@@ -3216,13 +3246,26 @@
 
 SWITCH_DECLARE(void) switch_core_session_signal_state_change(switch_core_session_t *session)
 {
+	switch_status_t status = SWITCH_STATUS_SUCCESS;
+	switch_io_event_hook_state_change_t *ptr;
 
 	/* If trylock fails the signal is already awake so we needn't bother */
 	if (switch_mutex_trylock(session->mutex) == SWITCH_STATUS_SUCCESS) {
 		switch_thread_cond_signal(session->cond);
 		switch_mutex_unlock(session->mutex);
 	} 
-	
+
+	if (session->endpoint_interface->io_routines->state_change) {
+		status = session->endpoint_interface->io_routines->state_change(session);
+	}
+
+	if (status == SWITCH_STATUS_SUCCESS) {
+		for (ptr = session->event_hooks.state_change; ptr; ptr = ptr->next) {
+			if ((status = ptr->state_change(session)) != SWITCH_STATUS_SUCCESS) {
+				break;
+			}
+		}
+	}
 }
 
 SWITCH_DECLARE(unsigned int) switch_core_session_running(switch_core_session_t *session)

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/switch_ivr.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/switch_ivr.c	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/switch_ivr.c	Wed Mar 28 13:40:13 2007
@@ -2498,7 +2498,7 @@
 	switch_frame_t *read_frame = NULL;
 	switch_memory_pool_t *pool = NULL;
 	int r = 0, i, and_argc = 0, or_argc = 0;
-	int32_t idx = IDX_NADA;
+	int32_t sleep_ms = 1000, try =0, retries = 1, idx = IDX_NADA;
 	switch_codec_t write_codec = {0};
 	switch_frame_t write_frame = {0};
 	uint8_t fdata[1024], pass = 0;
@@ -2512,6 +2512,8 @@
     switch_event_t *var_event = NULL;
 	uint8_t fail_on_single_reject = 0;
 	uint8_t ring_ready = 0;
+	char *loop_data = NULL;
+
 	write_frame.data = fdata;
 	
 	*bleg = NULL;
@@ -2605,7 +2607,7 @@
         }
     }
 
-	// When using the AND operator, the fail_on_single_reject flage may be set in order to indicate that a single
+	// When using the AND operator, the fail_on_single_reject flag may be set in order to indicate that a single
 	// rejections should terminate the attempt rather than a timeout, answer, or rejection by all.
 	if ((var = switch_event_get_header(var_event, "fail_on_single_reject")) && switch_true(var)) {
 		fail_on_single_reject = 1;
@@ -2619,6 +2621,28 @@
         early_ok = 0;
     }
 
+    if ((var_val = switch_event_get_header(var_event, "originate_retries")) && switch_true(var_val)) {
+		int32_t tmp;
+		tmp = atoi(var_val);
+		if (tmp > 0 && tmp < 101) {
+			retries = tmp;
+		} else {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, 
+							  "Invalid originate_retries setting of %d ignored, value must be between 1 and 100\n", tmp);
+		}
+    }
+
+    if ((var_val = switch_event_get_header(var_event, "originate_retry_sleep_ms")) && switch_true(var_val)) {
+		int32_t tmp;
+		tmp = atoi(var_val);
+		if (tmp > 500 && tmp < 60000) {
+			sleep_ms = tmp;
+		} else {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, 
+							  "Invalid originate_retry_sleep_ms setting of %d ignored, value must be between 500 and 60000\n", tmp);
+		}
+    }
+	
     if (!cid_name_override) {
         cid_name_override = switch_event_get_header(var_event, "origination_caller_id_name");
     }
@@ -2628,517 +2652,528 @@
     }
                                                         
 
-	or_argc = switch_separate_string(data, '|', pipe_names, (sizeof(pipe_names) / sizeof(pipe_names[0])));
-
-	if (caller_channel && or_argc > 1 && !ringback_data) {
-		switch_channel_ring_ready(caller_channel);
-		sent_ring = 1;
-	}
-
-	for (r = 0; r < or_argc; r++) {
-		uint32_t hups;
-        reason = SWITCH_CAUSE_UNALLOCATED;
-		memset(peer_names, 0, sizeof(peer_names));
-		peer_session = NULL;
-		memset(peer_sessions, 0, sizeof(peer_sessions));
-		memset(peer_channels, 0, sizeof(peer_channels));
-		memset(caller_profiles, 0, sizeof(caller_profiles));
-		chan_type = NULL;
-		chan_data = NULL;
-		peer_channel = NULL;
-		start = 0;
-		read_frame = NULL;
-		pool = NULL;
-		pass = 0;
-		file = NULL;
-		key = NULL;
-		var = NULL;
-		to = 0;
 
-		and_argc = switch_separate_string(pipe_names[r], ',', peer_names, (sizeof(peer_names) / sizeof(peer_names[0])));
-	
-		if (caller_channel && !sent_ring && and_argc > 1 && !ringback_data) {
+	for (try = 0; try < retries; try++) {
+		switch_safe_free(loop_data);
+		assert(loop_data = strdup(data));
+		or_argc = switch_separate_string(loop_data, '|', pipe_names, (sizeof(pipe_names) / sizeof(pipe_names[0])));
+		
+		if (caller_channel && or_argc > 1 && !ringback_data) {
 			switch_channel_ring_ready(caller_channel);
 			sent_ring = 1;
 		}
 
-		for (i = 0; i < and_argc; i++) {
-		
-			chan_type = peer_names[i];
-			if ((chan_data = strchr(chan_type, '/')) != 0) {
-				*chan_data = '\0';
-				chan_data++;
+		for (r = 0; r < or_argc; r++) {
+			uint32_t hups;
+			reason = SWITCH_CAUSE_UNALLOCATED;
+			memset(peer_names, 0, sizeof(peer_names));
+			peer_session = NULL;
+			memset(peer_sessions, 0, sizeof(peer_sessions));
+			memset(peer_channels, 0, sizeof(peer_channels));
+			memset(caller_profiles, 0, sizeof(caller_profiles));
+			chan_type = NULL;
+			chan_data = NULL;
+			peer_channel = NULL;
+			start = 0;
+			read_frame = NULL;
+			pool = NULL;
+			pass = 0;
+			file = NULL;
+			key = NULL;
+			var = NULL;
+			to = 0;
+			
+			if (try > 0) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Originate attempt %d/%d in %d ms\n", try + 1, retries, sleep_ms);
+				switch_yield(sleep_ms * 1000);
 			}
-	
-			if (session) {
-				if (!switch_channel_ready(caller_channel)) {
-					status = SWITCH_STATUS_FALSE;
-					goto done;
-				}
 
-				caller_caller_profile = caller_profile_override ? caller_profile_override : switch_channel_get_caller_profile(caller_channel);
-                
-				if (!cid_name_override) {
-					cid_name_override = caller_caller_profile->caller_id_name;
-				}
-				if (!cid_num_override) {
-					cid_num_override = caller_caller_profile->caller_id_number;
-				}
+			and_argc = switch_separate_string(pipe_names[r], ',', peer_names, (sizeof(peer_names) / sizeof(peer_names[0])));
+	
+			if (caller_channel && !sent_ring && and_argc > 1 && !ringback_data) {
+				switch_channel_ring_ready(caller_channel);
+				sent_ring = 1;
+			}
 
-				caller_profiles[i] = switch_caller_profile_new(switch_core_session_get_pool(session),
-															   caller_caller_profile->username,
-															   caller_caller_profile->dialplan,
-															   cid_name_override,
-															   cid_num_override,
-															   caller_caller_profile->network_addr,
-															   NULL,
-															   NULL,
-															   caller_caller_profile->rdnis,
-															   caller_caller_profile->source,
-															   caller_caller_profile->context,
-															   chan_data);
-				caller_profiles[i]->flags = caller_caller_profile->flags;
-				pool = NULL;
-			} else {
-				if (!cid_name_override) {
-					cid_name_override = "FreeSWITCH";
-				}
-				if (!cid_num_override) {
-					cid_num_override = "0000000000";
+			for (i = 0; i < and_argc; i++) {
+		
+				chan_type = peer_names[i];
+				if ((chan_data = strchr(chan_type, '/')) != 0) {
+					*chan_data = '\0';
+					chan_data++;
 				}
+	
+				if (session) {
+					if (!switch_channel_ready(caller_channel)) {
+						status = SWITCH_STATUS_FALSE;
+						goto done;
+					}
 
-				if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
-					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
-					status = SWITCH_STATUS_TERM;
-					goto done;
-				}
+					caller_caller_profile = caller_profile_override ? caller_profile_override : switch_channel_get_caller_profile(caller_channel);
+                
+					if (!cid_name_override) {
+						cid_name_override = caller_caller_profile->caller_id_name;
+					}
+					if (!cid_num_override) {
+						cid_num_override = caller_caller_profile->caller_id_number;
+					}
 
-				if (caller_profile_override) {
-					caller_profiles[i] = switch_caller_profile_new(pool,
-																   caller_profile_override->username,
-																   caller_profile_override->dialplan,
-																   caller_profile_override->caller_id_name,
-																   caller_profile_override->caller_id_number,
-																   caller_profile_override->network_addr, 
-																   caller_profile_override->ani,
-																   caller_profile_override->aniii,
-																   caller_profile_override->rdnis,
-																   caller_profile_override->source,
-																   caller_profile_override->context,
-																   chan_data);
-				} else {
-					caller_profiles[i] = switch_caller_profile_new(pool,
-																   NULL,
-																   NULL,
+					caller_profiles[i] = switch_caller_profile_new(switch_core_session_get_pool(session),
+																   caller_caller_profile->username,
+																   caller_caller_profile->dialplan,
 																   cid_name_override,
 																   cid_num_override,
+																   caller_caller_profile->network_addr,
 																   NULL,
-																   NULL, 
-																   NULL,
-																   NULL,
-																   __FILE__,
 																   NULL,
+																   caller_caller_profile->rdnis,
+																   caller_caller_profile->source,
+																   caller_caller_profile->context,
 																   chan_data);
+					caller_profiles[i]->flags = caller_caller_profile->flags;
+					pool = NULL;
+				} else {
+					if (!cid_name_override) {
+						cid_name_override = "FreeSWITCH";
+					}
+					if (!cid_num_override) {
+						cid_num_override = "0000000000";
+					}
+
+					if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
+						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
+						status = SWITCH_STATUS_TERM;
+						goto done;
+					}
+
+					if (caller_profile_override) {
+						caller_profiles[i] = switch_caller_profile_new(pool,
+																	   caller_profile_override->username,
+																	   caller_profile_override->dialplan,
+																	   caller_profile_override->caller_id_name,
+																	   caller_profile_override->caller_id_number,
+																	   caller_profile_override->network_addr, 
+																	   caller_profile_override->ani,
+																	   caller_profile_override->aniii,
+																	   caller_profile_override->rdnis,
+																	   caller_profile_override->source,
+																	   caller_profile_override->context,
+																	   chan_data);
+					} else {
+						caller_profiles[i] = switch_caller_profile_new(pool,
+																	   NULL,
+																	   NULL,
+																	   cid_name_override,
+																	   cid_num_override,
+																	   NULL,
+																	   NULL, 
+																	   NULL,
+																	   NULL,
+																	   __FILE__,
+																	   NULL,
+																	   chan_data);
+					}
 				}
-			}
 
-			if ((reason = switch_core_session_outgoing_channel(session, chan_type, caller_profiles[i], &peer_sessions[i], &pool)) != SWITCH_CAUSE_SUCCESS) {
-				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Create Outgoing Channel! cause: %s\n", switch_channel_cause2str(reason));
-				if (pool) {
-					switch_core_destroy_memory_pool(&pool);
-				}
-				caller_profiles[i] = NULL;
-				peer_channels[i] = NULL;
-				peer_sessions[i] = NULL;
-				continue;
-			}
+				if ((reason = switch_core_session_outgoing_channel(session, chan_type, caller_profiles[i], &peer_sessions[i], &pool)) != SWITCH_CAUSE_SUCCESS) {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Create Outgoing Channel! cause: %s\n", switch_channel_cause2str(reason));
+					if (pool) {
+						switch_core_destroy_memory_pool(&pool);
+					}
+					caller_profiles[i] = NULL;
+					peer_channels[i] = NULL;
+					peer_sessions[i] = NULL;
+					continue;
+				}
 			
-			switch_core_session_read_lock(peer_sessions[i]);
-			pool = NULL;
+				switch_core_session_read_lock(peer_sessions[i]);
+				pool = NULL;
 	
-			peer_channels[i] = switch_core_session_get_channel(peer_sessions[i]);
-			assert(peer_channels[i] != NULL);
+				peer_channels[i] = switch_core_session_get_channel(peer_sessions[i]);
+				assert(peer_channels[i] != NULL);
 
-			if (!table) {
-				table = &originate_state_handlers;
-			}
+				if (!table) {
+					table = &originate_state_handlers;
+				}
 
-			if (table) {
-				switch_channel_add_state_handler(peer_channels[i], table);
-			}
+				if (table) {
+					switch_channel_add_state_handler(peer_channels[i], table);
+				}
 
-			if (switch_core_session_running(peer_sessions[i])) {
-				switch_channel_set_state(peer_channels[i], CS_RING);
-			} else {
-				switch_core_session_thread_launch(peer_sessions[i]);
+				if (switch_core_session_running(peer_sessions[i])) {
+					switch_channel_set_state(peer_channels[i], CS_RING);
+				} else {
+					switch_core_session_thread_launch(peer_sessions[i]);
+				}
 			}
-		}
 
-		time(&start);
+			time(&start);
 
-		for (;;) {
-			uint32_t valid_channels = 0;
-			for (i = 0; i < and_argc; i++) {
-				int state;
+			for (;;) {
+				uint32_t valid_channels = 0;
+				for (i = 0; i < and_argc; i++) {
+					int state;
 
-				if (!peer_channels[i]) {
-					continue;
-				}
-				valid_channels++;
-				state = switch_channel_get_state(peer_channels[i]);
+					if (!peer_channels[i]) {
+						continue;
+					}
+					valid_channels++;
+					state = switch_channel_get_state(peer_channels[i]);
 			
-				if (state >= CS_HANGUP) {
-					goto notready;
-				} else if (state >= CS_RING) {
-					goto endfor1;
-				}
+					if (state >= CS_HANGUP) {
+						goto notready;
+					} else if (state >= CS_RING) {
+						goto endfor1;
+					}
 		
-				if (caller_channel && !switch_channel_ready(caller_channel)) {
-					goto notready;
-				}
+					if (caller_channel && !switch_channel_ready(caller_channel)) {
+						goto notready;
+					}
 				
-				if ((time(NULL) - start) > (time_t)timelimit_sec) {
-					to++;
-					idx = IDX_CANCEL;
-					goto notready;
+					if ((time(NULL) - start) > (time_t)timelimit_sec) {
+						to++;
+						idx = IDX_CANCEL;
+						goto notready;
+					}
+					switch_yield(1000);
 				}
-				switch_yield(1000);
-			}
 
-			if (valid_channels == 0) {
-				status = SWITCH_STATUS_GENERR;
-				goto done;
-			}
+				if (valid_channels == 0) {
+					status = SWITCH_STATUS_GENERR;
+					goto done;
+				}
 
-		}
-	endfor1:
+			}
+		endfor1:
 
-		if (ringback_data && !switch_channel_test_flag(caller_channel, CF_ANSWERED) && !switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA)) {
-			switch_channel_pre_answer(caller_channel);
-		}
+			if (ringback_data && !switch_channel_test_flag(caller_channel, CF_ANSWERED) && !switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA)) {
+				switch_channel_pre_answer(caller_channel);
+			}
 
-		if (session && (read_codec = switch_core_session_get_read_codec(session)) && 
-			(ringback_data || !switch_channel_test_flag(caller_channel, CF_NOMEDIA))) {
+			if (session && (read_codec = switch_core_session_get_read_codec(session)) && 
+				(ringback_data || !switch_channel_test_flag(caller_channel, CF_NOMEDIA))) {
 
-			if (!(pass = (uint8_t)switch_test_flag(read_codec, SWITCH_CODEC_FLAG_PASSTHROUGH))) {
-				if (switch_core_codec_init(&write_codec,
-										   "L16",
-										   NULL,
-										   read_codec->implementation->samples_per_second,
-										   read_codec->implementation->microseconds_per_frame / 1000,
-										   1,
-										   SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
-										   NULL,
-										   pool) == SWITCH_STATUS_SUCCESS) {
+				if (!(pass = (uint8_t)switch_test_flag(read_codec, SWITCH_CODEC_FLAG_PASSTHROUGH))) {
+					if (switch_core_codec_init(&write_codec,
+											   "L16",
+											   NULL,
+											   read_codec->implementation->samples_per_second,
+											   read_codec->implementation->microseconds_per_frame / 1000,
+											   1,
+											   SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
+											   NULL,
+											   pool) == SWITCH_STATUS_SUCCESS) {
 					
 					
-					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activation Success L16@%uhz 1 channel %dms\n",
-									  read_codec->implementation->samples_per_second,
-									  read_codec->implementation->microseconds_per_frame / 1000);
-					write_frame.codec = &write_codec;
-					write_frame.datalen = read_codec->implementation->bytes_per_frame;
-					write_frame.samples = write_frame.datalen / 2;
-					memset(write_frame.data, 255, write_frame.datalen);
+						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activation Success L16@%uhz 1 channel %dms\n",
+										  read_codec->implementation->samples_per_second,
+										  read_codec->implementation->microseconds_per_frame / 1000);
+						write_frame.codec = &write_codec;
+						write_frame.datalen = read_codec->implementation->bytes_per_frame;
+						write_frame.samples = write_frame.datalen / 2;
+						memset(write_frame.data, 255, write_frame.datalen);
 					
-					if (ringback_data) {
-						char *tmp_data = NULL;
+						if (ringback_data) {
+							char *tmp_data = NULL;
 						
-						switch_buffer_create_dynamic(&ringback.audio_buffer, 512, 1024, 0);
-						switch_buffer_create_dynamic(&ringback.loop_buffer, 512, 1024, 0);
+							switch_buffer_create_dynamic(&ringback.audio_buffer, 512, 1024, 0);
+							switch_buffer_create_dynamic(&ringback.loop_buffer, 512, 1024, 0);
 
-						if (*ringback_data == '/') {
-							char *ext;
+							if (*ringback_data == '/') {
+								char *ext;
 							
-							if ((ext = strrchr(ringback_data, '.'))) {
-								switch_core_session_set_read_codec(session, &write_codec);
-								ext++;
-							} else {
-								ringback.asis++;
-								write_frame.codec = read_codec;
-								ext = read_codec->implementation->iananame;
-								tmp_data = switch_mprintf("%s.%s", ringback_data, ext);
-								ringback_data = tmp_data;
-							}
+								if ((ext = strrchr(ringback_data, '.'))) {
+									switch_core_session_set_read_codec(session, &write_codec);
+									ext++;
+								} else {
+									ringback.asis++;
+									write_frame.codec = read_codec;
+									ext = read_codec->implementation->iananame;
+									tmp_data = switch_mprintf("%s.%s", ringback_data, ext);
+									ringback_data = tmp_data;
+								}
 
-							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Play Ringback File [%s]\n", ringback_data);
+								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Play Ringback File [%s]\n", ringback_data);
 
-							ringback.fhb.channels = read_codec->implementation->number_of_channels;
-							ringback.fhb.samplerate = read_codec->implementation->samples_per_second;
-							if (switch_core_file_open(&ringback.fhb,
-													  ringback_data,
-													  read_codec->implementation->number_of_channels,
-													  read_codec->implementation->samples_per_second,
-													  SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT,
-													  switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
-								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Playing File\n");
-								switch_safe_free(tmp_data);
-								goto notready;
-							}
-							ringback.fh = &ringback.fhb;
+								ringback.fhb.channels = read_codec->implementation->number_of_channels;
+								ringback.fhb.samplerate = read_codec->implementation->samples_per_second;
+								if (switch_core_file_open(&ringback.fhb,
+														  ringback_data,
+														  read_codec->implementation->number_of_channels,
+														  read_codec->implementation->samples_per_second,
+														  SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT,
+														  switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
+									switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Playing File\n");
+									switch_safe_free(tmp_data);
+									goto notready;
+								}
+								ringback.fh = &ringback.fhb;
 
 							
-						} else {
-							teletone_init_session(&ringback.ts, 0, teletone_handler, &ringback);
-							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Play Ringback Tone [%s]\n", ringback_data);
-							//ringback.ts.debug = 1;
-							//ringback.ts.debug_stream = switch_core_get_console();
-							if (teletone_run(&ringback.ts, ringback_data)) {
-								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Playing Tone\n");
-								teletone_destroy_session(&ringback.ts);
-								switch_buffer_destroy(&ringback.audio_buffer);
-								switch_buffer_destroy(&ringback.loop_buffer);
-								ringback_data = NULL;
+							} else {
+								teletone_init_session(&ringback.ts, 0, teletone_handler, &ringback);
+								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Play Ringback Tone [%s]\n", ringback_data);
+								//ringback.ts.debug = 1;
+								//ringback.ts.debug_stream = switch_core_get_console();
+								if (teletone_run(&ringback.ts, ringback_data)) {
+									switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Playing Tone\n");
+									teletone_destroy_session(&ringback.ts);
+									switch_buffer_destroy(&ringback.audio_buffer);
+									switch_buffer_destroy(&ringback.loop_buffer);
+									ringback_data = NULL;
+								}
 							}
+							switch_safe_free(tmp_data);
 						}
-						switch_safe_free(tmp_data);
+					} else {
+						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec Error!");
+						switch_channel_hangup(caller_channel, SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE);
+						read_codec = NULL;
 					}
-				} else {
-					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec Error!");
-					switch_channel_hangup(caller_channel, SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE);
-					read_codec = NULL;
 				}
 			}
-		}
         
-        if (ringback_data) {
-            early_ok = 0;
-        }
-
-        while ((!caller_channel || switch_channel_ready(caller_channel)) && 
-			   check_channel_status(peer_channels, peer_sessions, and_argc, &idx, &hups, file, key, early_ok, &ring_ready)) {
-
-			// When the AND operator is being used, and fail_on_single_reject is set, a hangup indicates that the call should fail.
-			if ((to = (uint8_t)((time(NULL) - start) >= (time_t)timelimit_sec)) || (fail_on_single_reject && hups)) {
-				idx = IDX_CANCEL;
-				goto notready;
+			if (ringback_data) {
+				early_ok = 0;
 			}
 
-			if (peer_sessions[0] && switch_core_session_dequeue_message(peer_sessions[0], &message) == SWITCH_STATUS_SUCCESS) {
-				if (session && !ringback_data && or_argc == 1 && and_argc == 1) { /* when there is only 1 channel to call and bridge and no ringback */
-					switch_core_session_receive_message(session, message);
+			while ((!caller_channel || switch_channel_ready(caller_channel)) && 
+				   check_channel_status(peer_channels, peer_sessions, and_argc, &idx, &hups, file, key, early_ok, &ring_ready)) {
+
+				// When the AND operator is being used, and fail_on_single_reject is set, a hangup indicates that the call should fail.
+				if ((to = (uint8_t)((time(NULL) - start) >= (time_t)timelimit_sec)) || (fail_on_single_reject && hups)) {
+					idx = IDX_CANCEL;
+					goto notready;
 				}
+
+				if (peer_sessions[0] && switch_core_session_dequeue_message(peer_sessions[0], &message) == SWITCH_STATUS_SUCCESS) {
+					if (session && !ringback_data && or_argc == 1 && and_argc == 1) { /* when there is only 1 channel to call and bridge and no ringback */
+						switch_core_session_receive_message(session, message);
+					}
 				
-				if (switch_test_flag(message, SCSMF_DYNAMIC)) {
-					switch_safe_free(message);
-				} else {
-					message = NULL;
+					if (switch_test_flag(message, SCSMF_DYNAMIC)) {
+						switch_safe_free(message);
+					} else {
+						message = NULL;
+					}
 				}
-			}
 
-			/* read from the channel while we wait if the audio is up on it */
-			if (session && (ringback_data || !switch_channel_test_flag(caller_channel, CF_NOMEDIA)) && 
-				(switch_channel_test_flag(caller_channel, CF_ANSWERED) || switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA))) {
-				switch_status_t status = switch_core_session_read_frame(session, &read_frame, 1000, 0);
+				/* read from the channel while we wait if the audio is up on it */
+				if (session && (ringback_data || !switch_channel_test_flag(caller_channel, CF_NOMEDIA)) && 
+					(switch_channel_test_flag(caller_channel, CF_ANSWERED) || switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA))) {
+					switch_status_t status = switch_core_session_read_frame(session, &read_frame, 1000, 0);
 			
-				if (!SWITCH_READ_ACCEPTABLE(status)) {
-					break;
-				}
+					if (!SWITCH_READ_ACCEPTABLE(status)) {
+						break;
+					}
 				
-				if (ring_ready && read_frame && !pass && !switch_test_flag(read_frame, SFF_CNG) && read_frame->datalen > 1) {
-					if (ringback.fh) {
-						uint8_t abuf[1024];
-						switch_size_t mlen, olen;
-						unsigned int pos = 0;
+					if (ring_ready && read_frame && !pass && !switch_test_flag(read_frame, SFF_CNG) && read_frame->datalen > 1) {
+						if (ringback.fh) {
+							uint8_t abuf[1024];
+							switch_size_t mlen, olen;
+							unsigned int pos = 0;
 
-						if (ringback.asis) {
-							mlen = read_frame->datalen;
-						} else {
-							mlen = read_frame->datalen  / 2;
-						}
+							if (ringback.asis) {
+								mlen = read_frame->datalen;
+							} else {
+								mlen = read_frame->datalen  / 2;
+							}
 
-						olen = mlen;
-						switch_core_file_read(ringback.fh, abuf, &olen);
-						
-						if (olen == 0) {
 							olen = mlen;
-							ringback.fh->speed = 0;
-							switch_core_file_seek(ringback.fh, &pos, 0, SEEK_SET);
 							switch_core_file_read(ringback.fh, abuf, &olen);
+						
 							if (olen == 0) {
+								olen = mlen;
+								ringback.fh->speed = 0;
+								switch_core_file_seek(ringback.fh, &pos, 0, SEEK_SET);
+								switch_core_file_read(ringback.fh, abuf, &olen);
+								if (olen == 0) {
+									break;
+								}
+							}
+							write_frame.data = abuf;
+							write_frame.datalen = (uint32_t) (ringback.asis ? olen : olen * 2);
+							if (switch_core_session_write_frame(session, &write_frame, 1000, 0) != SWITCH_STATUS_SUCCESS) {
 								break;
 							}
-						}
-						write_frame.data = abuf;
-						write_frame.datalen = (uint32_t) (ringback.asis ? olen : olen * 2);
-						if (switch_core_session_write_frame(session, &write_frame, 1000, 0) != SWITCH_STATUS_SUCCESS) {
-							break;
-						}
-					} else if (ringback.audio_buffer) {
-						if ((write_frame.datalen = (uint32_t)switch_buffer_read(ringback.audio_buffer,
-																				write_frame.data,
-																				write_frame.codec->implementation->bytes_per_frame)) <= 0) {
-							switch_buffer_t *tmp;
-							tmp = ringback.audio_buffer;
-							ringback.audio_buffer = ringback.loop_buffer;
-							ringback.loop_buffer = tmp;
+						} else if (ringback.audio_buffer) {
 							if ((write_frame.datalen = (uint32_t)switch_buffer_read(ringback.audio_buffer,
 																					write_frame.data,
 																					write_frame.codec->implementation->bytes_per_frame)) <= 0) {
-								break;
+								switch_buffer_t *tmp;
+								tmp = ringback.audio_buffer;
+								ringback.audio_buffer = ringback.loop_buffer;
+								ringback.loop_buffer = tmp;
+								if ((write_frame.datalen = (uint32_t)switch_buffer_read(ringback.audio_buffer,
+																						write_frame.data,
+																						write_frame.codec->implementation->bytes_per_frame)) <= 0) {
+									break;
+								}
 							}
 						}
-					}
 
-					if (switch_core_session_write_frame(session, &write_frame, 1000, 0) != SWITCH_STATUS_SUCCESS) {
-						break;
-					}
-					if (ringback.loop_buffer) {
-						switch_buffer_write(ringback.loop_buffer, write_frame.data, write_frame.datalen);
+						if (switch_core_session_write_frame(session, &write_frame, 1000, 0) != SWITCH_STATUS_SUCCESS) {
+							break;
+						}
+						if (ringback.loop_buffer) {
+							switch_buffer_write(ringback.loop_buffer, write_frame.data, write_frame.datalen);
+						}
 					}
-				}
 
-			} else {
-				switch_yield(1000);
-			}
+				} else {
+					switch_yield(1000);
+				}
 		
-		}
-
-	notready:
+			}
 
-		if (caller_channel && !switch_channel_ready(caller_channel)) {
-			idx = IDX_CANCEL;
-		}
+		notready:
 
-		if (session && (ringback_data || !switch_channel_test_flag(caller_channel, CF_NOMEDIA))) {
-			switch_core_session_reset(session);
-		}
+			if (caller_channel && !switch_channel_ready(caller_channel)) {
+				idx = IDX_CANCEL;
+			}
 
-		for (i = 0; i < and_argc; i++) {
-			if (!peer_channels[i]) {
-				continue;
+			if (session && (ringback_data || !switch_channel_test_flag(caller_channel, CF_NOMEDIA))) {
+				switch_core_session_reset(session);
 			}
-			if (i != idx) {
-				if (idx == IDX_CANCEL) {
-					if (to) {
-						reason = SWITCH_CAUSE_NO_ANSWER;
-                    } else {
-                        reason = SWITCH_CAUSE_ORIGINATOR_CANCEL;
-                    }
-				} else {
-					if (to) {
-						reason = SWITCH_CAUSE_NO_ANSWER;
-					} else if (and_argc > 1) {
-						reason = SWITCH_CAUSE_LOSE_RACE;
+
+			for (i = 0; i < and_argc; i++) {
+				if (!peer_channels[i]) {
+					continue;
+				}
+				if (i != idx) {
+					if (idx == IDX_CANCEL) {
+						if (to) {
+							reason = SWITCH_CAUSE_NO_ANSWER;
+						} else {
+							reason = SWITCH_CAUSE_ORIGINATOR_CANCEL;
+						}
 					} else {
-						reason = SWITCH_CAUSE_NO_ANSWER;
+						if (to) {
+							reason = SWITCH_CAUSE_NO_ANSWER;
+						} else if (and_argc > 1) {
+							reason = SWITCH_CAUSE_LOSE_RACE;
+						} else {
+							reason = SWITCH_CAUSE_NO_ANSWER;
+						}
 					}
-				}
 
 				
-				switch_channel_hangup(peer_channels[i], reason);
+					switch_channel_hangup(peer_channels[i], reason);
+				}
 			}
-		}
 
 
-		if (idx > IDX_NADA) {
-			peer_session = peer_sessions[idx];
-			peer_channel = peer_channels[idx];
-		} else {
-			status = SWITCH_STATUS_FALSE;
-			goto done;
-		}
+			if (idx > IDX_NADA) {
+				peer_session = peer_sessions[idx];
+				peer_channel = peer_channels[idx];
+			} else {
+				status = SWITCH_STATUS_FALSE;
+				goto done;
+			}
 
-		if (caller_channel) {
-			if (switch_channel_test_flag(peer_channel, CF_ANSWERED)) {
-				switch_channel_answer(caller_channel);
-			} else if (switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA)) {
-				switch_channel_pre_answer(caller_channel);
+			if (caller_channel) {
+				if (switch_channel_test_flag(peer_channel, CF_ANSWERED)) {
+					switch_channel_answer(caller_channel);
+				} else if (switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA)) {
+					switch_channel_pre_answer(caller_channel);
+				}
 			}
-		}
 
-		if (switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA)) {
-			*bleg = peer_session;
-			status = SWITCH_STATUS_SUCCESS;
-		} else {
-			status = SWITCH_STATUS_FALSE;
-		}
+			if (switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA)) {
+				*bleg = peer_session;
+				status = SWITCH_STATUS_SUCCESS;
+			} else {
+				status = SWITCH_STATUS_FALSE;
+			}
 
-	done:
-		*cause = SWITCH_CAUSE_UNALLOCATED;
+		done:
+			*cause = SWITCH_CAUSE_UNALLOCATED;
         
-        if (var_event) {
-			if (peer_channel && !caller_channel) { /* install the vars from the {} params */
-                switch_event_header_t *header;
-                for (header = var_event->headers; header; header = header->next) {
-                    switch_channel_set_variable(peer_channel, header->name, header->value);
-                }
-            }
-            switch_event_destroy(&var_event);
-        }
+			if (var_event) {
+				if (peer_channel && !caller_channel) { /* install the vars from the {} params */
+					switch_event_header_t *header;
+					for (header = var_event->headers; header; header = header->next) {
+						switch_channel_set_variable(peer_channel, header->name, header->value);
+					}
+				}
+				switch_event_destroy(&var_event);
+			}
 
-		if (status == SWITCH_STATUS_SUCCESS) {
-			if (caller_channel) {
-				switch_channel_set_variable(caller_channel, "originate_disposition", "call accepted");
-			} 
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Originate Resulted in Success: [%s]\n", switch_channel_get_name(peer_channel));
-            *cause = SWITCH_CAUSE_SUCCESS;
+			if (status == SWITCH_STATUS_SUCCESS) {
+				if (caller_channel) {
+					switch_channel_set_variable(caller_channel, "originate_disposition", "call accepted");
+				} 
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Originate Resulted in Success: [%s]\n", switch_channel_get_name(peer_channel));
+				*cause = SWITCH_CAUSE_SUCCESS;
             
-		} else {
-			if (peer_channel) {
-				*cause = switch_channel_get_cause(peer_channel);
 			} else {
-				for (i = 0; i < and_argc; i++) {
-					if (!peer_channels[i]) {
-						continue;
+				if (peer_channel) {
+					*cause = switch_channel_get_cause(peer_channel);
+				} else {
+					for (i = 0; i < and_argc; i++) {
+						if (!peer_channels[i]) {
+							continue;
+						}
+						*cause = switch_channel_get_cause(peer_channels[i]);
+						break;
 					}
-                    *cause = switch_channel_get_cause(peer_channels[i]);
-					break;
 				}
-			}
 
-            if (!*cause) {
-                if (reason) {
-                    *cause = reason;
-                } else if (caller_channel) {
-                    *cause = switch_channel_get_cause(caller_channel);
-                } else {
-                    *cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
-                }
-            }
+				if (!*cause) {
+					if (reason) {
+						*cause = reason;
+					} else if (caller_channel) {
+						*cause = switch_channel_get_cause(caller_channel);
+					} else {
+						*cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+					}
+				}
 
-			if (idx == IDX_CANCEL) {
-				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Originate Cancelled by originator termination Cause: %d [%s]\n",
-								  *cause, switch_channel_cause2str(*cause));
+				if (idx == IDX_CANCEL) {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Originate Cancelled by originator termination Cause: %d [%s]\n",
+									  *cause, switch_channel_cause2str(*cause));
                 
-			} else {
-                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Originate Resulted in Error Cause: %d [%s]\n",
-								  *cause, switch_channel_cause2str(*cause));
+				} else {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Originate Resulted in Error Cause: %d [%s]\n",
+									  *cause, switch_channel_cause2str(*cause));
+				}
 			}
-		}
         
-        if (caller_channel) {
-            switch_channel_set_variable(caller_channel, "originate_disposition", switch_channel_cause2str(*cause));
-        }
-
-		if (!pass && write_codec.implementation) {
-			switch_core_codec_destroy(&write_codec);
-		}
+			if (caller_channel) {
+				switch_channel_set_variable(caller_channel, "originate_disposition", switch_channel_cause2str(*cause));
+			}
 
-		if (ringback.fh) {
-			switch_core_file_close(ringback.fh);
-			ringback.fh = NULL;
-			if (read_codec && !ringback.asis) {
-				switch_core_session_set_read_codec(session, read_codec);
-				switch_core_session_reset(session);
+			if (!pass && write_codec.implementation) {
+				switch_core_codec_destroy(&write_codec);
 			}
-		} else if (ringback.audio_buffer) {
-			teletone_destroy_session(&ringback.ts);
-			switch_buffer_destroy(&ringback.audio_buffer);
-			switch_buffer_destroy(&ringback.loop_buffer);
-		}
 
-		for (i = 0; i < and_argc; i++) {
-			if (!peer_channels[i]) {
-				continue;
+			if (ringback.fh) {
+				switch_core_file_close(ringback.fh);
+				ringback.fh = NULL;
+				if (read_codec && !ringback.asis) {
+					switch_core_session_set_read_codec(session, read_codec);
+					switch_core_session_reset(session);
+				}
+			} else if (ringback.audio_buffer) {
+				teletone_destroy_session(&ringback.ts);
+				switch_buffer_destroy(&ringback.audio_buffer);
+				switch_buffer_destroy(&ringback.loop_buffer);
 			}
-			switch_core_session_rwunlock(peer_sessions[i]);
-		}
 
-		if (status == SWITCH_STATUS_SUCCESS) {
-			break;
+			for (i = 0; i < and_argc; i++) {
+				if (!peer_channels[i]) {
+					continue;
+				}
+				switch_core_session_rwunlock(peer_sessions[i]);
+			}
+			
+			if (status == SWITCH_STATUS_SUCCESS) {
+				goto outer_for;
+			}
 		}
 	}
-
+ outer_for:
+	switch_safe_free(loop_data);
 	switch_safe_free(odata);
 	return status;
 }



More information about the Freeswitch-svn mailing list