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

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Jun 28 16:56:43 CDT 2013


Author: mmichelson
Date: Fri Jun 28 16:56:41 2013
New Revision: 393237

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=393237
Log:
Flesh out the retransfer state.

I can now successfully recall both the transfer target and the transferer
when atxferdropcall is set to no.

Next step will be making sure that everything works in a nice cyclical matter.


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=393237&r1=393236&r2=393237
==============================================================================
--- team/mmichelson/atxfer_features/main/bridging_basic.c (original)
+++ team/mmichelson/atxfer_features/main/bridging_basic.c Fri Jun 28 16:56:41 2013
@@ -277,7 +277,6 @@
 {
 	struct ast_channel *chan;
 	int cause;
-
 
 	/* Now we request a local channel to prepare to call the destination */
 	chan = ast_request("Local", ast_channel_nativeformats(caller), caller, destination,
@@ -939,6 +938,8 @@
 	ast_dial_join(props->dial);
 	ast_dial_destroy(props->dial);
 	props->dial = NULL;
+	/* This reference is the one we incremented for the dial state callback (recall_callback) to use */
+	ao2_ref(props, -1);
 
 	switch (stimulus) {
 	default:
@@ -966,23 +967,84 @@
 	}
 }
 
+static int attach_framehook(struct attended_transfer_properties *props, struct ast_channel *channel);
+
 static int retransfer_enter(struct attended_transfer_properties *props)
 {
-	/* XXX Need to do the following:
-	 * 1) Request new transfer target channel
-	 * 2) Create a new target bridge (or maybe just reuse old one?)
-	 * 3) Place target channel into target bridge
-	 * 4) Place outgoing call to party C
-	 * 5) Stimulate a change to BLOND state
-	 */
+	RAII_VAR(struct ast_format_cap *, cap, ast_format_cap_alloc_nolock(), ast_format_cap_destroy);
+	struct ast_format fmt;
+	char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2];
+	int cause;
+
+	if (props->recall_target) {
+		ast_log(LOG_NOTICE, "props->recall_target is non-NULL and its refcount is %d\n", ao2_ref(props->recall_target, 0));
+	} else {
+		ast_log(LOG_NOTICE, "props->recall_target is NULL\n");
+	}
+	
+	if (!cap) {
+		return -1;
+	}
+
+	snprintf(destination, sizeof(destination), "%s@%s", props->exten, props->context);
+
+	ast_format_cap_add(cap, ast_format_set(&fmt, AST_FORMAT_SLINEAR, 0));
+
+	/* Get a channel that is the destination we wish to call */
+	props->recall_target = ast_request("Local", cap, NULL, destination, &cause);
+	if (!props->recall_target) {
+		ast_log(LOG_ERROR, "Unable to request outbound channel for recall target\n");
+		return -1;
+	}
+
+	if (attach_framehook(props, props->recall_target)) {
+		ast_log(LOG_ERROR, "Unable to attach framehook to recall target\n");
+		ast_hangup(props->recall_target);
+		props->recall_target = NULL;
+		return -1;
+	}
+
+	if (ast_call(props->recall_target, destination, 0)) {
+		ast_log(LOG_ERROR, "Unable to place outbound call to recall target\n");
+		ast_hangup(props->recall_target);
+		props->recall_target = NULL;
+		return -1;
+	}
+
+	ast_channel_ref(props->recall_target);
+	if (ast_bridge_impart(props->transferee_bridge, props->recall_target, NULL, NULL, 1)) {
+		ast_log(LOG_ERROR, "Unable to place recall target into bridge\n");
+		ast_hangup(props->recall_target);
+		return -1;
+	}
+
 	return 0;
 }
 
 static enum attended_transfer_state retransfer_next(struct attended_transfer_properties *props,
 		enum attended_transfer_stimulus stimulus)
 {
-	/* XXX This is no longer correct */
-	return TRANSFER_BLOND;
+	switch (stimulus) {
+	default:
+	case STIMULUS_NONE:
+	case STIMULUS_DTMF_ATXFER_ABORT:
+	case STIMULUS_DTMF_ATXFER_COMPLETE:
+	case STIMULUS_DTMF_ATXFER_THREEWAY:
+	case STIMULUS_DTMF_ATXFER_SWAP:
+	case STIMULUS_TRANSFER_TARGET_HANGUP:
+	case STIMULUS_TRANSFER_TARGET_ANSWER:
+	case STIMULUS_TRANSFERER_HANGUP:
+		ast_assert(0);
+	case STIMULUS_TRANSFEREE_HANGUP:
+		return TRANSFER_FAIL;
+	case STIMULUS_TIMEOUT:
+		ast_softhangup(props->recall_target, AST_SOFTHANGUP_EXPLICIT);
+		props->recall_target = ast_channel_unref(props->recall_target);
+	case STIMULUS_RECALL_TARGET_HANGUP:
+		return TRANSFER_RECALLING;
+	case STIMULUS_RECALL_TARGET_ANSWER:
+		return TRANSFER_RESUME;
+	}
 }
 
 static int fail_enter(struct attended_transfer_properties *props)
@@ -1142,7 +1204,11 @@
 	if (event == AST_FRAMEHOOK_EVENT_READ &&
 			frame && frame->frametype == AST_FRAME_CONTROL &&
 			frame->subclass.integer == AST_CONTROL_ANSWER) {
-		stimulate_attended_transfer(props, STIMULUS_TRANSFER_TARGET_ANSWER);
+		if (props->superstate == STATE_TRANSFER) {
+			stimulate_attended_transfer(props, STIMULUS_TRANSFER_TARGET_ANSWER);
+		} else {
+			stimulate_attended_transfer(props, STIMULUS_RECALL_TARGET_ANSWER);
+		}
 		ast_framehook_detach(chan, props->target_framehook_id);
 		props->target_framehook_id = -1;
 	}
@@ -1169,7 +1235,6 @@
 	case AST_DIAL_RESULT_UNANSWERED:
 		/* Failure cases */
 		stimulate_attended_transfer(props, STIMULUS_RECALL_TARGET_HANGUP);
-		ao2_ref(props, -1);
 		break;
 	case AST_DIAL_RESULT_RINGING:
 	case AST_DIAL_RESULT_PROGRESS:
@@ -1185,11 +1250,8 @@
 		 */
 		ast_channel_ref(props->recall_target);
 		stimulate_attended_transfer(props, STIMULUS_RECALL_TARGET_ANSWER);
-		ao2_ref(props, -1);
 		break;
 	}
-
-
 }
 
 static int bridge_personality_atxfer_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
@@ -1391,7 +1453,7 @@
 	return NULL;
 }
 
-static int attach_framehook(struct attended_transfer_properties *props)
+static int attach_framehook(struct attended_transfer_properties *props, struct ast_channel *channel)
 {
 	struct ast_framehook_interface target_interface = {
 		.version = AST_FRAMEHOOK_INTERFACE_VERSION,
@@ -1402,7 +1464,7 @@
 	ao2_ref(props, +1);
 	target_interface.data = props;
 
-	props->target_framehook_id = ast_framehook_attach(props->transfer_target, &target_interface);
+	props->target_framehook_id = ast_framehook_attach(channel, &target_interface);
 	if (props->target_framehook_id == -1) {
 		ao2_ref(props, -1);
 		return -1;
@@ -1509,7 +1571,7 @@
 	}
 	ast_bridge_merge_inhibit(props->target_bridge, +1);
 
-	if (attach_framehook(props)) {
+	if (attach_framehook(props, props->transfer_target)) {
 		ast_log(LOG_ERROR, "Unable to attach framehook to transfer target\n");
 		ast_stream_and_wait(props->transferer, props->failsound, AST_DIGIT_NONE);
 		ast_bridge_channel_write_unhold(bridge_channel);
@@ -1601,8 +1663,6 @@
 	struct bridge_basic_personality *personality;
 	SCOPED_LOCK(lock, bridge, ast_bridge_lock, ast_bridge_unlock);
 
-	ast_assert(bridge->v_table == &ast_bridge_base_v_table);
-
 	personality = normal_personality_alloc();
 	ao2_cleanup(bridge->personality);
 	bridge->personality = personality;
@@ -1622,8 +1682,6 @@
 {
 	struct bridge_basic_personality *personality;
 	SCOPED_LOCK(lock, bridge, ast_bridge_lock, ast_bridge_unlock);
-
-	ast_assert(bridge->v_table == &ast_bridge_base_v_table);
 
 	personality = atxfer_personality_alloc(props);
 	ao2_cleanup(bridge->personality);




More information about the asterisk-commits mailing list