[asterisk-commits] mmichelson: branch mmichelson/atxfer_features r392278 - /team/mmichelson/atxf...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jun 19 16:52:57 CDT 2013


Author: mmichelson
Date: Wed Jun 19 16:52:55 2013
New Revision: 392278

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=392278
Log:
Address some hold/unhold areas in the state machine.

This also addressed some other odds and ends as I came
across them.


Modified:
    team/mmichelson/atxfer_features/main/bridging_basic.c

Modified: team/mmichelson/atxfer_features/main/bridging_basic.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/atxfer_features/main/bridging_basic.c?view=diff&rev=392278&r1=392277&r2=392278
==============================================================================
--- team/mmichelson/atxfer_features/main/bridging_basic.c (original)
+++ team/mmichelson/atxfer_features/main/bridging_basic.c Wed Jun 19 16:52:55 2013
@@ -370,8 +370,9 @@
 
 	ao2_cleanup(props->target_bridge);
 	ao2_cleanup(props->transferee_bridge);
-	ast_channel_unref(props->transferer);
-	ast_channel_unref(props->transfer_target);
+	/* Use ao2_cleanup() instead of ast_channel_unref() for channels since they may be NULL */
+	ao2_cleanup(props->transferer);
+	ao2_cleanup(props->transfer_target);
 	ast_cond_destroy(&props->cond);
 	ast_mutex_destroy(&props->lock);
 	AST_LIST_HEAD_DESTROY(&props->stimulus_queue);
@@ -407,6 +408,32 @@
 	props->atxfercallbackretries = atxfercallbackretries;
 
 	return props;
+}
+
+static void hold(struct ast_channel *chan)
+{
+	RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
+
+	ast_channel_lock(chan);
+	bridge_channel = ast_channel_get_bridge_channel(chan);
+	ast_channel_unlock(chan);
+	
+	ast_assert(bridge_channel != NULL);
+
+	ast_bridge_channel_write_hold(bridge_channel, NULL);
+}
+
+static void unhold(struct ast_channel *chan)
+{
+	RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
+
+	ast_channel_lock(chan);
+	bridge_channel = ast_channel_get_bridge_channel(chan);
+	ast_channel_unlock(chan);
+	
+	ast_assert(bridge_channel != NULL);
+
+	ast_bridge_channel_write_unhold(bridge_channel);
 }
 
 /*!
@@ -432,6 +459,11 @@
 		return TRANSFER_FAIL;
 	case STIMULUS_DTMF_ATXFER_COMPLETE:
 	case STIMULUS_TRANSFERER_HANGUP:
+		/* XXX For this state change, I need to take the
+		 * transferee off hold, but the transferer is not in the
+		 * bridge. Can I just write directly to the bridge?
+		 * Queue it on the bridge?
+		 */
 		return TRANSFER_BLOND;
 	case STIMULUS_TARGET_ANSWER:
 		return TRANSFER_CONSULTING;
@@ -448,7 +480,12 @@
 
 static int hesitant_enter(struct attended_transfer_properties *props)
 {
-	return ast_bridge_move(props->transferee_bridge, props->target_bridge, props->transferer, NULL, 1);
+	if (ast_bridge_move(props->transferee_bridge, props->target_bridge, props->transferer, NULL, 1)) {
+		return -1;
+	}
+
+	unhold(props->transferer);
+	return 0;
 }
 
 static enum attended_transfer_state hesitant_next(struct attended_transfer_properties *props,
@@ -473,32 +510,49 @@
 	case STIMULUS_DTMF_ATXFER_THREEWAY:
 		return TRANSFER_THREEWAY;
 	case STIMULUS_DTMF_ATXFER_SWAP:
-		return TRANSFER_HESITANT;
+		hold(props->transferer);
+		return TRANSFER_CALLING_TARGET;
 	}
 }
 
 static int rebridge_enter(struct attended_transfer_properties *props)
 {
-	return ast_bridge_move(props->transferee_bridge, props->target_bridge,
-			props->transferer, NULL, 1);
+	if (ast_bridge_move(props->transferee_bridge, props->target_bridge,
+			props->transferer, NULL, 1)) {
+		return -1;
+	}
+
+	unhold(props->transferer);
+	return 0;
 }
 
 static int resume_enter(struct attended_transfer_properties *props)
 {
+	ast_bridge_basic_change_personality_normal(props->transferee_bridge);
 	return ast_bridge_destroy(props->target_bridge);
 }
 
 static int threeway_enter(struct attended_transfer_properties *props)
 {
-	return ast_bridge_merge(props->transferee_bridge, props->target_bridge, 0, NULL, 0);
+	if (ast_bridge_merge(props->transferee_bridge, props->target_bridge, 0, NULL, 0)) {
+		return -1;
+	}
+
+	/* XXX After the bridge merge, the transferee_bridge will be a softmix
+	 * bridge. If one of the involved bridges was a simple bridge and the
+	 * participant was on hold, then will this unhold properly remove the hold
+	 * from the channel?
+	 */
+	unhold(props->transferer);
+	return 0;
 }
 
 static int consulting_enter(struct attended_transfer_properties *props)
 {
-	struct ast_bridge *transferer_bridge;
+	RAII_VAR(struct ast_bridge *, transferer_bridge, NULL, ao2_cleanup);
 
 	ast_channel_lock(props->transferer);
-	transferer_bridge = ast_channel_internal_bridge(props->transferer);
+	transferer_bridge = ast_channel_get_bridge(props->transferer);
 	ast_channel_unlock(props->transferer);
 
 	ast_assert(transferer_bridge != NULL);
@@ -506,7 +560,12 @@
 	if (transferer_bridge == props->target_bridge) {
 		return 0;
 	}
-	return ast_bridge_move(props->target_bridge, props->transferee_bridge, props->transferer, NULL, 1);
+
+	if (ast_bridge_move(props->target_bridge, props->transferee_bridge, props->transferer, NULL, 1)) {
+		return -1;
+	}
+	unhold(props->transferer);
+	return 0;
 }
 
 static enum attended_transfer_state consulting_next(struct attended_transfer_properties *props,
@@ -531,6 +590,7 @@
 	case STIMULUS_DTMF_ATXFER_THREEWAY:
 		 return TRANSFER_THREEWAY;
 	case STIMULUS_DTMF_ATXFER_SWAP:
+		 hold(props->transferer);
 		 return TRANSFER_DOUBLECHECKING;
 	}
 }
@@ -548,7 +608,11 @@
 	if (transferer_bridge == props->transferee_bridge) {
 		return 0;
 	}
-	return ast_bridge_move(props->transferee_bridge, props->target_bridge, props->transferer, NULL, 1);
+	if (ast_bridge_move(props->transferee_bridge, props->target_bridge, props->transferer, NULL, 1)) {
+		return -1;
+	}
+	unhold(props->transferer);
+	return 0;
 }
 
 static enum attended_transfer_state double_checking_next(struct attended_transfer_properties *props,
@@ -572,13 +636,22 @@
 	case STIMULUS_DTMF_ATXFER_THREEWAY:
 		 return TRANSFER_THREEWAY;
 	case STIMULUS_DTMF_ATXFER_SWAP:
+		 hold(props->transferer);
 		 return TRANSFER_CONSULTING;
 	}
 }
 
 static int complete_enter(struct attended_transfer_properties *props)
 {
-	return ast_bridge_merge(props->transferee_bridge, props->target_bridge, 0, &props->transferer, 1);
+	if (ast_bridge_merge(props->transferee_bridge, props->target_bridge, 0, &props->transferer, 1)) {
+		return -1;
+	}
+
+	/* XXX Same unhold concern here as in the threeway state. However, there
+	 * is no guarantee here that the resulting bridge's technology will be.
+	 */
+	unhold(props->transferer);
+	return 0;
 }
 
 static int blond_enter(struct attended_transfer_properties *props)
@@ -587,6 +660,7 @@
 		return 0;
 	}
 	ast_softhangup(props->transferer, AST_SOFTHANGUP_EXPLICIT);
+	props->transferer = ast_channel_unref(props->transferer);
 	return 0;
 }
 
@@ -609,15 +683,15 @@
 		return TRANSFER_COMPLETE;
 	case STIMULUS_TARGET_HANGUP:
 	case STIMULUS_TIMEOUT:
+		if (props->atxferdropcall) {
+			return TRANSFER_FAIL;
+		}
 		return TRANSFER_RECALLING;
 	}
 }
 
 static int recalling_enter(struct attended_transfer_properties *props)
 {
-	if (props->atxferdropcall) {
-		return -1;
-	}
 	/* XXX Need to:
 	 * 1) Request transferer channel
 	 * 2) Add transferer role to channel
@@ -644,6 +718,10 @@
 	case STIMULUS_TRANSFEREE_HANGUP:
 		return TRANSFER_FAIL;
 	case STIMULUS_TIMEOUT:
+		++props->retry_attempts;
+		if (props->retry_attempts >= props->atxfercallbackretries) {
+			return TRANSFER_FAIL;
+		}
 		return TRANSFER_RETRANSFER;
 	case STIMULUS_TRANSFERER_ANSWER:
 		return TRANSFER_RESUME;
@@ -652,10 +730,6 @@
 
 static int retransfer_enter(struct attended_transfer_properties *props)
 {
-	++props->retry_attempts;
-	if (props->retry_attempts >= props->atxfercallbackretries) {
-		return -1;
-	}
 	/* XXX Need to do the following:
 	 * 1) Request new transfer target channel
 	 * 2) Create a new target bridge (or maybe just reuse old one?)




More information about the asterisk-commits mailing list