[Freeswitch-svn] [commit] r7885 - in freeswitch/trunk/src: . include mod/applications/mod_commands mod/applications/mod_dptools

Freeswitch SVN anthm at freeswitch.org
Wed Mar 12 21:08:42 EDT 2008


Author: anthm
Date: Wed Mar 12 21:08:42 2008
New Revision: 7885

Modified:
   freeswitch/trunk/src/include/switch_types.h
   freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c
   freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
   freeswitch/trunk/src/switch_core_state_machine.c
   freeswitch/trunk/src/switch_ivr.c
   freeswitch/trunk/src/switch_ivr_async.c
   freeswitch/trunk/src/switch_ivr_bridge.c
   freeswitch/trunk/src/switch_ivr_originate.c
   freeswitch/trunk/src/switch_ivr_play_say.c
   freeswitch/trunk/src/switch_rtp.c

Log:
the same guy who added att xfer to asterisk was nice enough to add it to freeswitch too

Modified: freeswitch/trunk/src/include/switch_types.h
==============================================================================
--- freeswitch/trunk/src/include/switch_types.h	(original)
+++ freeswitch/trunk/src/include/switch_types.h	Wed Mar 12 21:08:42 2008
@@ -102,6 +102,9 @@
 #define SWITCH_PATH_SEPARATOR "/"
 #endif
 #define SWITCH_URL_SEPARATOR "://"
+#define SWITCH_CALL_TIMEOUT_VARIABLE "call_timeout"
+#define SWITCH_HOLDING_UUID_VARIABLE "holding_uuid"
+#define SWITCH_API_BRIDGE_END_VARIABLE "api_after_bridge"
 #define SWITCH_API_HANGUP_HOOK_VARIABLE "api_hangup_hook"
 #define SWITCH_PROCESS_CDR_VARIABLE "process_cdr"
 #define SWITCH_BRIDGE_CHANNEL_VARIABLE "bridge_channel"
@@ -564,7 +567,8 @@
 	SWITCH_STATUS_MORE_DATA,
 	SWITCH_STATUS_NOTFOUND,
 	SWITCH_STATUS_UNLOAD,
-	SWITCH_STATUS_NOUNLOAD
+	SWITCH_STATUS_NOUNLOAD,
+	SWITCH_STATUS_IGNORE
 } switch_status_t;
 
 
@@ -717,7 +721,8 @@
 	CF_RESET = (1 << 24),
 	CF_ORIGINATING = (1 << 25),
 	CF_STOP_BROADCAST = (1 << 26),
-	CF_PROXY_MEDIA = (1 << 27)
+	CF_PROXY_MEDIA = (1 << 27),
+	CF_INNER_BRIDGE = (1 << 28)
 } switch_channel_flag_t;
 
 

Modified: freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c	Wed Mar 12 21:08:42 2008
@@ -1172,10 +1172,25 @@
 		argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
 	}
 
-	if (switch_strlen_zero(cmd) || argc != 2) {
+	if (switch_strlen_zero(cmd) || argc < 2) {
 		stream->write_function(stream, "-USAGE: %s\n", UUID_SYNTAX);
 	} else {
-		if (switch_ivr_uuid_bridge(argv[0], argv[1]) != SWITCH_STATUS_SUCCESS) {
+		switch_status_t status;
+		char *who = NULL;
+		
+		if ((status = switch_ivr_uuid_bridge(argv[0], argv[1])) != SWITCH_STATUS_SUCCESS) {
+			if (argv[2]) {
+				if ((status = switch_ivr_uuid_bridge(argv[0], argv[2])) == SWITCH_STATUS_SUCCESS) {
+					who = argv[2];
+				}
+			} 
+		} else {
+			who = argv[1];
+		}
+
+		if (status == SWITCH_STATUS_SUCCESS) {
+			stream->write_function(stream, "+OK %s\n", who);
+		} else {
 			stream->write_function(stream, "-ERR Invalid uuid\n");
 		}
 	}

Modified: freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c	Wed Mar 12 21:08:42 2008
@@ -222,6 +222,8 @@
 						switch_ivr_session_transfer(b_session, argv[1], argv[2], argv[3]);
 						switch_core_session_rwunlock(b_session);
 					}
+				} else {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No B-leg present.\n");
 				}
 				if (both) {
 					switch_ivr_session_transfer(session, argv[1], argv[2], argv[3]);
@@ -1109,6 +1111,146 @@
 	switch_ivr_speak_text(session, engine, voice, text, &args);
 }
 
+static switch_status_t xfer_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
+{
+	switch_core_session_t *peer_session = (switch_core_session_t *) buf;
+
+	if (!buf || !peer_session) {
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	switch (itype) {
+	case SWITCH_INPUT_TYPE_DTMF:
+		{			
+			switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
+			switch_channel_t *channel = switch_core_session_get_channel(session);
+			switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
+			
+			if (dtmf->digit == '#') {
+				return SWITCH_STATUS_FALSE;
+			}
+
+			if (dtmf->digit == '0') {
+				switch_caller_extension_t *extension = NULL;
+				const char *app = "three_way";
+				const char *app_arg = switch_core_session_get_uuid(session);
+				const char *holding = switch_channel_get_variable(channel, SWITCH_HOLDING_UUID_VARIABLE);
+				switch_core_session_t *b_session;
+
+				if (holding && (b_session = switch_core_session_locate(holding))) {
+					switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
+					if (!switch_channel_ready(b_channel)) {
+						app = "intercept";
+					}
+					switch_core_session_rwunlock(b_session);
+				}
+				
+				if ((extension = switch_caller_extension_new(peer_session, app, app_arg)) == 0) {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "memory error!\n");
+					abort();
+				}
+				
+				switch_caller_extension_add_application(peer_session, extension, app, app_arg);
+				switch_channel_set_caller_extension(peer_channel, extension);
+				switch_channel_set_flag(peer_channel, CF_TRANSFER);
+				switch_channel_set_state(peer_channel, CS_EXECUTE);
+
+				return SWITCH_STATUS_FALSE;
+			}
+			
+		}
+		break;
+	default:
+		break;
+	}
+
+	return SWITCH_STATUS_SUCCESS;
+
+
+}
+
+static switch_status_t hanguphook(switch_core_session_t *session)
+{
+	switch_channel_t *channel = switch_core_session_get_channel(session);
+	switch_channel_state_t state = switch_channel_get_state(channel);
+	const char *id = NULL;
+
+	if (state == CS_HANGUP || state == CS_RING) {
+		if ((id = switch_channel_get_variable(channel, "xfer_uuids"))) {
+			switch_stream_handle_t stream = { 0 };
+			SWITCH_STANDARD_STREAM(stream);
+			switch_api_execute("uuid_bridge", id, NULL, &stream);
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "\nHangup Command uuid_bridge(%s):\n%s\n", id, switch_str_nil((char *) stream.data));
+			switch_safe_free(stream.data);
+		}
+		
+		switch_core_event_hook_remove_state_change(session, hanguphook);
+	}
+	return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_APP(att_xfer_function)
+{
+	const char *var;
+	switch_core_session_t *peer_session = NULL;
+	switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
+	switch_channel_t *channel, *peer_channel = NULL;
+	const char *bond = NULL;
+	int timelimit = 60;
+
+	channel = switch_core_session_get_channel(session);
+
+	if ((bond = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
+		bond = switch_core_session_strdup(session, bond);
+	}
+
+	switch_channel_set_variable(channel, SWITCH_HOLDING_UUID_VARIABLE, bond);
+	
+	
+	if ((var = switch_channel_get_variable(channel, SWITCH_CALL_TIMEOUT_VARIABLE))) {
+		timelimit = atoi(var);
+	}
+
+	if (switch_ivr_originate(session, &peer_session, &cause, data, timelimit, NULL, NULL, NULL, NULL, SOF_NONE) != SWITCH_STATUS_SUCCESS) {
+		return;
+	}
+
+	peer_channel = switch_core_session_get_channel(peer_session);
+	switch_channel_set_flag(peer_channel, CF_INNER_BRIDGE);
+	switch_channel_set_flag(channel, CF_INNER_BRIDGE);
+	
+	switch_ivr_multi_threaded_bridge(session, peer_session, xfer_on_dtmf, peer_session, NULL);
+	
+	if (bond) {
+		switch_core_session_t *b_session;
+		char buf[128] = "";
+
+		if ((b_session = switch_core_session_locate(bond))) {
+			switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
+			switch_snprintf(buf, sizeof(buf), "%s %s", switch_core_session_get_uuid(peer_session), switch_core_session_get_uuid(session));
+			switch_channel_set_variable(b_channel, "xfer_uuids", buf);
+
+			switch_snprintf(buf, sizeof(buf), "%s %s", switch_core_session_get_uuid(peer_session), bond);
+			switch_channel_set_variable(channel, "xfer_uuids", buf);
+			
+			switch_core_event_hook_add_state_change(session, hanguphook);
+			switch_core_event_hook_add_state_change(b_session, hanguphook);
+
+			switch_core_session_rwunlock(b_session);
+		}
+		
+		switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond);
+	}
+
+	if (peer_session) {
+		switch_core_session_rwunlock(peer_session);
+	}
+	
+	switch_channel_set_variable(channel, SWITCH_HOLDING_UUID_VARIABLE, NULL);
+
+}
+
+
 
 SWITCH_STANDARD_APP(read_function)
 {
@@ -1126,7 +1268,7 @@
 	if (!switch_strlen_zero(data) && (mydata = switch_core_session_strdup(session, data))) {
 		argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
 	} else {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No file specified.\n");		
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No arguements specified.\n");		
 		return;
 	}
 
@@ -1347,7 +1489,7 @@
 		return;
 	}
 
-	if ((var = switch_channel_get_variable(caller_channel, "call_timeout"))) {
+	if ((var = switch_channel_get_variable(caller_channel, SWITCH_CALL_TIMEOUT_VARIABLE))) {
 		timelimit = atoi(var);
 	}
 
@@ -1516,13 +1658,13 @@
 
 		if (session) {
 			channel = switch_core_session_get_channel(session);
-			if ((var = switch_channel_get_variable(channel, "call_timeout"))) {
+			if ((var = switch_channel_get_variable(channel, SWITCH_CALL_TIMEOUT_VARIABLE))) {
 				timelimit = atoi(var);
 			}
 			
 			switch_channel_set_variable(channel, "dialed_user", user);
 			switch_channel_set_variable(channel, "dialed_domain", domain);
-
+			
 			d_dest = switch_channel_expand_variables(channel, dest);
 
 		} else {
@@ -1650,7 +1792,7 @@
 	SWITCH_ADD_APP(app_interface, "sched_broadcast", SCHED_BROADCAST_DESCR, SCHED_BROADCAST_DESCR, sched_broadcast_function, "[+]<time> <path> [aleg|bleg|both]", SAF_SUPPORT_NOMEDIA);
 	SWITCH_ADD_APP(app_interface, "sched_transfer", SCHED_TRANSF_DESCR, SCHED_TRANSF_DESCR, sched_transfer_function, "[+]<time> <extension> <dialplan> <context>", SAF_SUPPORT_NOMEDIA);
 	SWITCH_ADD_APP(app_interface, "execute_extension", "Execute an extension", "Execute an extension", exe_function, EXE_SYNTAX, SAF_SUPPORT_NOMEDIA);
-	SWITCH_ADD_APP(app_interface, "bind_meta_app", "Bind a key to an application", "Bind a key to an application", dtmf_bind_function, BIND_SYNTAX, SAF_NONE);
+	SWITCH_ADD_APP(app_interface, "bind_meta_app", "Bind a key to an application", "Bind a key to an application", dtmf_bind_function, BIND_SYNTAX, SAF_SUPPORT_NOMEDIA);
 	SWITCH_ADD_APP(app_interface, "intercept", "intercept", "intercept", intercept_function, INTERCEPT_SYNTAX, SAF_NONE);
 	SWITCH_ADD_APP(app_interface, "eavesdrop", "eavesdrop on a uuid", "eavesdrop on a uuid", eavesdrop_function, eavesdrop_SYNTAX, SAF_NONE);
 	SWITCH_ADD_APP(app_interface, "three_way", "three way call with a uuid", "three way call with a uuid", three_way_function, eavesdrop_SYNTAX, SAF_NONE);
@@ -1668,6 +1810,7 @@
 	SWITCH_ADD_APP(app_interface, "park_state", "Park State", "Park State", park_state_function, "", SAF_NONE);
 	SWITCH_ADD_APP(app_interface, "gentones", "Generate Tones", "Generate tones to the channel", gentones_function, "<tgml_script>[|<loops>]", SAF_NONE);
 	SWITCH_ADD_APP(app_interface, "playback", "Playback File", "Playback a file to the channel", playback_function, "<path>", SAF_NONE);
+	SWITCH_ADD_APP(app_interface, "att_xfer", "Read Digits", "Read Digits", att_xfer_function, "foo>", SAF_NONE);
 	SWITCH_ADD_APP(app_interface, "read", "Read Digits", "Read Digits", read_function, "<min> <max> <file> <var name> <timeout> <terminators>", SAF_NONE);
 	SWITCH_ADD_APP(app_interface, "stop_record_session", "Stop Record Session", STOP_SESS_REC_DESC, stop_record_session_function, "<path>", SAF_NONE);
 	SWITCH_ADD_APP(app_interface, "record_session", "Record Session", SESS_REC_DESC, record_session_function, "<path>", SAF_NONE);

Modified: freeswitch/trunk/src/switch_core_state_machine.c
==============================================================================
--- freeswitch/trunk/src/switch_core_state_machine.c	(original)
+++ freeswitch/trunk/src/switch_core_state_machine.c	Wed Mar 12 21:08:42 2008
@@ -412,7 +412,7 @@
 			case CS_HANGUP:	    /* Deactivate and end the thread */
 				{
 					const char *var = switch_channel_get_variable(session->channel, SWITCH_PROCESS_CDR_VARIABLE);
-					const char *hook_var = switch_channel_get_variable(session->channel, SWITCH_API_HANGUP_HOOK_VARIABLE);
+					const char *hook_var;
 
 					if (!switch_strlen_zero(var)) {
 						if (!strcasecmp(var, "a_only")) {
@@ -431,6 +431,8 @@
 					STATE_MACRO(hangup, "HANGUP");
 					switch_core_session_signal_unlock(session);
 
+					hook_var = switch_channel_get_variable(session->channel, SWITCH_API_HANGUP_HOOK_VARIABLE);
+
 					if (!switch_strlen_zero(hook_var)) {
 						switch_stream_handle_t stream = { 0 };
 						char *cmd = switch_core_session_strdup(session, hook_var);
@@ -439,7 +441,7 @@
 							*arg++ = '\0';
 						}
 						SWITCH_STANDARD_STREAM(stream);
-						switch_api_execute(cmd, arg, session, &stream);
+						switch_api_execute(cmd, arg, NULL, &stream);
 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Hangup Command %s(%s):\n%s\n", cmd, arg, switch_str_nil((char *) stream.data));
 						switch_safe_free(stream.data);
 					}

Modified: freeswitch/trunk/src/switch_ivr.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr.c	(original)
+++ freeswitch/trunk/src/switch_ivr.c	Wed Mar 12 21:08:42 2008
@@ -310,6 +310,7 @@
 					if (hold_bleg && switch_true(hold_bleg)) {
 						if ((b_uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
 							const char *stream;
+							b_uuid = switch_core_session_strdup(session, b_uuid);
 
 							if (!(stream = switch_channel_get_variable_partner(channel, SWITCH_HOLD_MUSIC_VARIABLE))) {
 								stream = switch_channel_get_variable(channel, SWITCH_HOLD_MUSIC_VARIABLE);
@@ -318,7 +319,6 @@
 							if (stream) {
 								if ((b_session = switch_core_session_locate(b_uuid))) {
 									switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
-
 									switch_ivr_broadcast(b_uuid, stream, SMF_ECHO_ALEG | SMF_LOOP);
 									switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_TRUE, 5000);
 									switch_core_session_rwunlock(b_session);
@@ -336,6 +336,7 @@
 							break;
 						}
 					}
+
 					if (b_uuid) {
 						if ((b_session = switch_core_session_locate(b_uuid))) {
 							switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
@@ -344,6 +345,7 @@
 							switch_core_session_rwunlock(b_session);
 						}
 					}
+
 					switch_channel_clear_flag(channel, CF_BROADCAST);					
 				}
 			}

Modified: freeswitch/trunk/src/switch_ivr_async.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr_async.c	(original)
+++ freeswitch/trunk/src/switch_ivr_async.c	Wed Mar 12 21:08:42 2008
@@ -1277,8 +1277,8 @@
 	time_t now = switch_timestamp(NULL);
 	char digit[2] = "";
 	int dval;
-
-	if (!md) {
+	
+	if (!md || switch_channel_test_flag(channel, CF_INNER_BRIDGE)) {
 		return SWITCH_STATUS_SUCCESS;
 	}
 

Modified: freeswitch/trunk/src/switch_ivr_bridge.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr_bridge.c	(original)
+++ freeswitch/trunk/src/switch_ivr_bridge.c	Wed Mar 12 21:08:42 2008
@@ -98,6 +98,8 @@
 	switch_core_session_t *session_a, *session_b;
 	uint32_t loop_count = 0;
 	const char *app_name = NULL, *app_arg = NULL;
+	const char *hook_var = NULL;
+	int nosuspend  = 0;
 #ifdef SWITCH_VIDEO_IN_THREADS
     struct vid_helper vh = { 0 };
 	uint32_t vid_launch = 0;
@@ -122,7 +124,9 @@
 	}
 
 	switch_channel_set_flag(chan_a, CF_BRIDGED);
-
+	
+	nosuspend = switch_channel_test_flag(chan_a, CF_INNER_BRIDGE);
+	
 	for (;;) {
 		switch_channel_state_t b_state;
 		switch_status_t status;
@@ -130,17 +134,17 @@
 		loop_count++;
 
 		if (!switch_channel_ready(chan_a)) {
-			break;
+			goto end_of_bridge_loop;
 		}
 
 		if ((b_state = switch_channel_get_state(chan_b)) >= CS_HANGUP) {
-			break;
+			goto end_of_bridge_loop;
 		}
 
 		if (switch_channel_test_flag(chan_a, CF_TRANSFER) || switch_channel_test_flag(chan_b, CF_TRANSFER)) {
 			switch_channel_clear_flag(chan_a, CF_HOLD);
 			switch_channel_clear_flag(chan_a, CF_SUSPEND);
-			break;
+			goto end_of_bridge_loop;
 		}
 
 		if (loop_count > 50 && switch_core_session_private_event_count(session_a)) {
@@ -155,8 +159,8 @@
 			switch_channel_clear_flag(chan_b, CF_SUSPEND);
 		}
 		
-		if (switch_channel_test_flag(chan_a, CF_SUSPEND) || switch_channel_test_flag(chan_b, CF_SUSPEND)) {
-			switch_yield(1000);
+		if (!nosuspend && (switch_channel_test_flag(chan_a, CF_SUSPEND) || switch_channel_test_flag(chan_b, CF_SUSPEND))) {
+			switch_yield(10000);
 			continue;
 		}
 
@@ -173,16 +177,23 @@
 		while (switch_channel_has_dtmf(chan_a)) {
 			switch_dtmf_t dtmf = { 0, 0 };
 			if (switch_channel_dequeue_dtmf(chan_a, &dtmf) == SWITCH_STATUS_SUCCESS) {
+				int send_dtmf = 1;
+				
 				if (input_callback) {
-					if (input_callback(session_a, (void *)&dtmf, SWITCH_INPUT_TYPE_DTMF, user_data, 0) != SWITCH_STATUS_SUCCESS) {
+					switch_status_t cb_status = input_callback(session_a, (void *)&dtmf, SWITCH_INPUT_TYPE_DTMF, user_data, 0);
+					
+					if (cb_status == SWITCH_STATUS_IGNORE) {
+						send_dtmf = 0;
+					} if (cb_status != SWITCH_STATUS_SUCCESS) {
 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s ended call via DTMF\n", switch_channel_get_name(chan_a));
 						switch_core_session_kill_channel(session_b, SWITCH_SIG_BREAK);
-						break;
+						goto end_of_bridge_loop;
 					}
 				}
 				
-
-				switch_core_session_send_dtmf(session_b, &dtmf);
+				if (send_dtmf) {
+					switch_core_session_send_dtmf(session_b, &dtmf);
+				}
 			}
 		}
 
@@ -211,13 +222,13 @@
 			if (!ans_b && switch_channel_test_flag(chan_b, CF_ANSWERED)) {
 				if (switch_channel_answer(chan_a) != SWITCH_STATUS_SUCCESS) {
 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Media Establishment Failed.\n", switch_channel_get_name(chan_a));
-					break;
+					goto end_of_bridge_loop;
 				}
 				ans_a++;
 			} else if (!pre_b && switch_channel_test_flag(chan_b, CF_EARLY_MEDIA)) {
 				if (switch_channel_pre_answer(chan_a) != SWITCH_STATUS_SUCCESS) {
 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Media Establishment Failed.\n", switch_channel_get_name(chan_a));
-					break;
+					goto end_of_bridge_loop;
 				}
 				pre_b++;
 			}
@@ -233,7 +244,7 @@
 			status = switch_core_session_read_video_frame(session_a, &read_frame, -1, 0);
 		
 			if (!SWITCH_READ_ACCEPTABLE(status)) {
-				break;
+				goto end_of_bridge_loop;
 			}
 		
 			switch_core_session_write_video_frame(session_b, read_frame, -1, 0);
@@ -252,15 +263,18 @@
 				if (switch_core_session_write_frame(session_b, read_frame, -1, stream_id) != SWITCH_STATUS_SUCCESS) {
 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "write: %s Bad Frame....[%u] Bubye!\n",
 									  switch_channel_get_name(chan_b), read_frame->datalen);
-					break;
+					goto end_of_bridge_loop;
 				}
 			}
 		} else {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "read: %s Bad Frame.... Bubye!\n", switch_channel_get_name(chan_a));
-			break;
+			goto end_of_bridge_loop;
 		}
 	}
 
+ end_of_bridge_loop:
+
+
 #ifdef SWITCH_VIDEO_IN_THREADS
     if (vh.up) {
         vh.up = -1;
@@ -271,7 +285,24 @@
     }
 #endif
 
+	if (!nosuspend) {
+		hook_var = switch_channel_get_variable(chan_a, SWITCH_API_BRIDGE_END_VARIABLE);
+	}
 
+	if (!switch_strlen_zero(hook_var)) {
+		switch_stream_handle_t stream = { 0 };
+		char *cmd = switch_core_session_strdup(session_a, hook_var);
+		char *arg = NULL;
+		if ((arg = strchr(cmd, ' '))) {
+			*arg++ = '\0';
+		}
+		SWITCH_STANDARD_STREAM(stream);
+		switch_api_execute(cmd, arg, NULL, &stream);
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "\nPost-Bridge Command %s(%s):\n%s\n", cmd, arg, switch_str_nil((char *) stream.data));
+		switch_safe_free(stream.data);
+	}
+	
+	
 	if (switch_channel_get_state(chan_b) >= CS_HANGUP) {	
 		if (originator && switch_channel_ready(chan_a) && !switch_channel_test_flag(chan_a, CF_ANSWERED)) {
 			switch_channel_hangup(chan_a, switch_channel_get_cause(chan_b));
@@ -282,8 +313,8 @@
 	msg.message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE;
 	msg.from = __FILE__;
 	switch_core_session_receive_message(session_a, &msg);
-
-	if (switch_channel_get_state(chan_a) < CS_HANGUP) {
+	
+	if (!nosuspend && switch_channel_get_state(chan_a) < CS_HANGUP) {
 		if ((app_name = switch_channel_get_variable(chan_a, SWITCH_EXEC_AFTER_BRIDGE_APP_VARIABLE))) {
 			switch_caller_extension_t *extension = NULL;
 			if ((extension = switch_caller_extension_new(session_a, app_name, app_name)) == 0) {
@@ -412,12 +443,18 @@
 
 		switch_channel_wait_for_state(channel, other_channel, CS_RESET);
 
+		if (switch_ivr_wait_for_answer(session, other_session) != SWITCH_STATUS_SUCCESS) {
+			switch_core_session_rwunlock(other_session);
+			switch_channel_hangup(channel, SWITCH_CAUSE_ORIGINATOR_CANCEL);
+			return SWITCH_STATUS_FALSE;
+		}
+
 		if (switch_channel_get_state(other_channel) == CS_RESET) {
 			switch_channel_set_state(other_channel, CS_TRANSMIT);
 		}
 
 		switch_channel_wait_for_state(channel, other_channel, CS_TRANSMIT);
-		
+
 		switch_channel_clear_flag(channel, CF_TRANSFER);
 		switch_channel_clear_flag(other_channel, CF_TRANSFER);
 		switch_core_session_reset(session, SWITCH_TRUE);
@@ -743,6 +780,9 @@
 
   done:
 
+	switch_channel_clear_flag(caller_channel, CF_INNER_BRIDGE);
+	switch_channel_clear_flag(peer_channel, CF_INNER_BRIDGE);
+
 	if (br && switch_event_create(&event, SWITCH_EVENT_CHANNEL_UNBRIDGE) == SWITCH_STATUS_SUCCESS) {
 		switch_channel_event_set_data(caller_channel, event);
 		switch_event_fire(&event);
@@ -773,6 +813,13 @@
 			originator_channel = switch_core_session_get_channel(originator_session);
 			originatee_channel = switch_core_session_get_channel(originatee_session);
 
+			if (switch_channel_get_state(originator_channel) >= CS_HANGUP) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s is hungup refusing to bridge.\n", switch_channel_get_name(originatee_channel));
+				switch_core_session_rwunlock(originator_session);
+				switch_core_session_rwunlock(originatee_session);
+				return SWITCH_STATUS_FALSE;
+			}
+
 			if (!switch_channel_test_flag(originator_channel, CF_ANSWERED)) {
 				if (switch_channel_test_flag(originatee_channel, CF_ANSWERED)) {
 					swap_session = originator_session;
@@ -861,10 +908,10 @@
 
 		} else {
 			switch_core_session_rwunlock(originator_session);
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "no channel for originatee uuid %s\n", originatee_uuid);
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "originatee uuid %s is not present\n", originatee_uuid);
 		}
 	} else {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "no channel for originator uuid %s\n", originator_uuid);
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "originator uuid %s is not present\n", originator_uuid);
 	}
 
 	return status;

Modified: freeswitch/trunk/src/switch_ivr_originate.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr_originate.c	(original)
+++ freeswitch/trunk/src/switch_ivr_originate.c	Wed Mar 12 21:08:42 2008
@@ -367,7 +367,7 @@
 		}
 	}
 
-	while (!(switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA))) {
+	while (switch_channel_ready(peer_channel) && !(switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA))) {
 		int diff = (int)(switch_timestamp_now() - start);
 		
 		if (diff > timelimit) {
@@ -1120,6 +1120,8 @@
 				}
 
 				if (i != idx) {
+					const char *holding = NULL;
+					
 					if (idx == IDX_CANCEL) {
 						if (to) {
 							reason = SWITCH_CAUSE_NO_ANSWER;
@@ -1135,9 +1137,17 @@
 							reason = SWITCH_CAUSE_NO_ANSWER;
 						}
 					}
-
-
-					switch_channel_hangup(peer_channels[i], reason);
+					
+					if (caller_channel && i == 0) {
+						holding = switch_channel_get_variable(caller_channel, SWITCH_HOLDING_UUID_VARIABLE);
+						holding = switch_core_session_strdup(session, holding);
+						switch_channel_set_variable(caller_channel, SWITCH_HOLDING_UUID_VARIABLE, NULL);
+					}
+					if (holding) {
+						switch_ivr_uuid_bridge(holding, switch_core_session_get_uuid(peer_sessions[i]));
+					} else {
+						switch_channel_hangup(peer_channels[i], reason);
+					}
 				}
 			}
 

Modified: freeswitch/trunk/src/switch_ivr_play_say.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr_play_say.c	(original)
+++ freeswitch/trunk/src/switch_ivr_play_say.c	Wed Mar 12 21:08:42 2008
@@ -1126,15 +1126,16 @@
 	args.buf = digit_buffer;
 	args.buflen = digit_buffer_length;
 
-	if (!switch_strlen_zero(prompt_audio_file)) {
+	if (!switch_strlen_zero(prompt_audio_file) && strcasecmp(prompt_audio_file, "silence")) {
 		status = switch_ivr_play_file(session, NULL, prompt_audio_file, &args);
 	}
-
+	
 	if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
 		goto end;
 	}
 
 	len = strlen(digit_buffer);
+	
 
 	if (len < min_digits && len < max_digits) {
 		args.buf = digit_buffer + len;
@@ -1142,7 +1143,7 @@
 		status = switch_ivr_collect_digits_count(session, digit_buffer, digit_buffer_length, max_digits, valid_terminators, &terminator, timeout, 0, 0);
 	}
 
-
+	
  end:
 
 	if (var_name && !switch_strlen_zero(digit_buffer)) {

Modified: freeswitch/trunk/src/switch_rtp.c
==============================================================================
--- freeswitch/trunk/src/switch_rtp.c	(original)
+++ freeswitch/trunk/src/switch_rtp.c	Wed Mar 12 21:08:42 2008
@@ -1143,8 +1143,18 @@
 				switch_core_timer_sync(&rtp_session->timer);
 			} else {
 				check = (uint8_t) (switch_core_timer_check(&rtp_session->timer, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS);						
+				if (check && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_AUTO_CNG) &&
+					rtp_session->timer.samplecount >= (rtp_session->last_write_samplecount + (rtp_session->samples_per_interval * 50))) {
+					uint8_t data[10] = { 0 };
+					switch_frame_flag_t frame_flags = SFF_NONE;
+					data[0] = 65;
+					rtp_session->cn++;
+					rtp_common_write(rtp_session, NULL, (void *) data, 2, rtp_session->cng_pt, 0, &frame_flags);
+				}
 			}
-		} 
+		} else if (bytes) {
+			check++;
+		}
 
 		if (check) {
 			do_2833(rtp_session);
@@ -1295,19 +1305,6 @@
 			goto end;
 		}
 
-		if (rtp_session->timer.interval) {
-			if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_AUTO_CNG) &&
-				rtp_session->timer.samplecount >= (rtp_session->last_write_samplecount + (rtp_session->samples_per_interval * 50))) {
-				uint8_t data[10] = { 0 };
-				switch_frame_flag_t frame_flags = SFF_NONE;
-				data[0] = 65;
-				rtp_session->cn++;
-				switch_mutex_lock(rtp_session->flag_mutex);
-				rtp_common_write(rtp_session, NULL, (void *) data, 2, rtp_session->cng_pt, 0, &frame_flags);
-				switch_mutex_unlock(rtp_session->flag_mutex);
-			}
-		}
-
 		if (check || (bytes && !rtp_session->timer.interval)) {
 			if (!bytes && rtp_session->max_missed_packets) {
 				if (++rtp_session->missed_count >= rtp_session->max_missed_packets) {



More information about the Freeswitch-svn mailing list