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

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sat Jun 29 14:18:29 CDT 2013


Author: mmichelson
Date: Sat Jun 29 14:18:27 2013
New Revision: 393282

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=393282
Log:
Add states to delay between recall attempts.

Now the atxferloopdelay option actually does something! Yay!
In between recall states, the transferee will be placed on hold
for a brief period before attempting to recall the appropriate
parties.


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=393282&r1=393281&r2=393282
==============================================================================
--- team/mmichelson/atxfer_features/main/bridging_basic.c (original)
+++ team/mmichelson/atxfer_features/main/bridging_basic.c Sat Jun 29 14:18:27 2013
@@ -355,8 +355,12 @@
 	TRANSFER_BLOND_NONFINAL,
 	/* Transfer target did not answer, re-call transferer */
 	TRANSFER_RECALLING,
+	/* Transferer did not answer re-call, wait a bit */
+	TRANSFER_WAIT_TO_RETRANSFER,
 	/* Transferer did not answer re-call, re-call transfer target */
 	TRANSFER_RETRANSFER,
+	/* Transfer target did not answer re-call, wait a bit */
+	TRANSFER_WAIT_TO_RECALL,
 	/* The transfer did not succeed. All parties will disappear */
 	TRANSFER_FAIL,
 };
@@ -405,12 +409,13 @@
 	struct ast_channel *transfer_target;
 	struct ast_channel *recall_target;
 	struct timeval start;
-	struct timeval timeout;
 	AST_LIST_HEAD(,stimulus_list) stimulus_queue;
 	enum attended_transfer_state state;
 	enum attended_transfer_superstate superstate;
 	int atxferdropcall;
 	int atxfercallbackretries;
+	int atxferloopdelay;
+	int atxfernoanswertimeout;
 	int retry_attempts;
 	int target_framehook_id;
 	char exten[AST_MAX_EXTENSION];
@@ -469,7 +474,8 @@
 	}
 	props->atxferdropcall = xfer_cfg->atxferdropcall;
 	props->atxfercallbackretries = xfer_cfg->atxfercallbackretries;
-	props->timeout = ast_samp2tv(xfer_cfg->atxfernoanswertimeout, 1000);
+	props->atxfernoanswertimeout = xfer_cfg->atxfernoanswertimeout;
+	props->atxferloopdelay = xfer_cfg->atxferloopdelay;
 	ast_copy_string(props->context, get_transfer_context(transferer, context), sizeof(props->context));
 	ast_copy_string(props->failsound, xfer_cfg->xferfailsound, sizeof(props->failsound));
 
@@ -570,6 +576,16 @@
 	ast_assert(bridge_channel != NULL);
 
 	ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_RINGING, NULL, 0);
+}
+
+static void bridge_hold(struct ast_bridge *bridge)
+{
+	struct ast_frame hold = {
+		.frametype = AST_FRAME_CONTROL,
+		.subclass.integer = AST_CONTROL_HOLD,
+	};
+
+	ast_bridge_queue_everyone_else(bridge, NULL, &hold);
 }
 
 static void bridge_unhold(struct ast_bridge *bridge)
@@ -952,10 +968,43 @@
 		if (props->retry_attempts >= props->atxfercallbackretries) {
 			return TRANSFER_FAIL;
 		}
+		if (props->atxferloopdelay) {
+			return TRANSFER_WAIT_TO_RETRANSFER;
+		}
 		return TRANSFER_RETRANSFER;
 	case STIMULUS_RECALL_TARGET_ANSWER:
 		ast_bridge_impart(props->transferee_bridge, props->recall_target, NULL, NULL, 1);
 		return TRANSFER_RESUME;
+	}
+}
+
+static int wait_to_retransfer_enter(struct attended_transfer_properties *props)
+{
+	bridge_hold(props->transferee_bridge);
+	return 0;
+}
+
+static enum attended_transfer_state wait_to_retransfer_next(struct attended_transfer_properties *props,
+		enum attended_transfer_stimulus stimulus)
+{
+	bridge_unhold(props->transferee_bridge);
+	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:
+	case STIMULUS_RECALL_TARGET_HANGUP:
+	case STIMULUS_RECALL_TARGET_ANSWER:
+		ast_assert(0);
+	case STIMULUS_TRANSFEREE_HANGUP:
+		return TRANSFER_FAIL;
+	case STIMULUS_TIMEOUT:
+		return TRANSFER_RETRANSFER;
 	}
 }
 
@@ -1033,9 +1082,42 @@
 		ast_softhangup(props->recall_target, AST_SOFTHANGUP_EXPLICIT);
 	case STIMULUS_RECALL_TARGET_HANGUP:
 		props->recall_target = ast_channel_unref(props->recall_target);
+		if (props->atxferloopdelay) {
+			return TRANSFER_WAIT_TO_RECALL;
+		}
 		return TRANSFER_RECALLING;
 	case STIMULUS_RECALL_TARGET_ANSWER:
 		return TRANSFER_RESUME;
+	}
+}
+
+static int wait_to_recall_enter(struct attended_transfer_properties *props)
+{
+	bridge_hold(props->transferee_bridge);
+	return 0;
+}
+
+static enum attended_transfer_state wait_to_recall_next(struct attended_transfer_properties *props,
+		enum attended_transfer_stimulus stimulus)
+{
+	bridge_unhold(props->transferee_bridge);
+	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:
+	case STIMULUS_RECALL_TARGET_HANGUP:
+	case STIMULUS_RECALL_TARGET_ANSWER:
+		ast_assert(0);
+	case STIMULUS_TRANSFEREE_HANGUP:
+		return TRANSFER_FAIL;
+	case STIMULUS_TIMEOUT:
+		return TRANSFER_RECALLING;
 	}
 }
 
@@ -1052,6 +1134,7 @@
 	TRANSFER_STATE_IS_TIMED = (1 << 0),
 	TRANSFER_STATE_RESET_TIMER = (1 << 1),
 	TRANSFER_STATE_IS_TERMINAL = (1 << 2),
+	TRANSFER_STATE_TIMER_LOOP_DELAY = (1 << 3),
 };
 
 static struct attended_transfer_state_properties {
@@ -1120,11 +1203,23 @@
 		.next = recalling_next,
 		.flags = TRANSFER_STATE_IS_TIMED | TRANSFER_STATE_RESET_TIMER,
 	},
+	[TRANSFER_WAIT_TO_RETRANSFER] = {
+		.state_name = "Wait to Retransfer",
+		.enter = wait_to_retransfer_enter,
+		.next = wait_to_retransfer_next,
+		.flags = TRANSFER_STATE_IS_TIMED | TRANSFER_STATE_RESET_TIMER | TRANSFER_STATE_TIMER_LOOP_DELAY,
+	},
 	[TRANSFER_RETRANSFER] = {
 		.state_name = "Retransfer",
 		.enter = retransfer_enter,
 		.next = retransfer_next,
 		.flags = TRANSFER_STATE_IS_TIMED | TRANSFER_STATE_RESET_TIMER,
+	},
+	[TRANSFER_WAIT_TO_RECALL] = {
+		.state_name = "Wait to Recall",
+		.enter = wait_to_recall_enter,
+		.next = wait_to_recall_next,
+		.flags = TRANSFER_STATE_IS_TIMED | TRANSFER_STATE_RESET_TIMER | TRANSFER_STATE_TIMER_LOOP_DELAY,
 	},
 	[TRANSFER_FAIL] = {
 		.state_name = "Fail",
@@ -1394,15 +1489,23 @@
 		if (!(state_properties[props->state].flags & TRANSFER_STATE_IS_TIMED)) {
 			ast_cond_wait(&props->cond, lock);
 		} else {
-			struct timeval timeout;
+			struct timeval relative_timeout;
+			struct timeval absolute_timeout;
 			struct timespec timeout_arg;
 
 			if (state_properties[props->state].flags & TRANSFER_STATE_RESET_TIMER) {
 				props->start = ast_tvnow();
 			}
-			timeout = ast_tvadd(props->start, props->timeout);
-			timeout_arg.tv_sec = timeout.tv_sec;
-			timeout_arg.tv_nsec = timeout.tv_usec * 1000;
+
+			if (state_properties[props->state].flags & TRANSFER_STATE_TIMER_LOOP_DELAY) {
+				relative_timeout = ast_samp2tv(props->atxferloopdelay, 1000);
+			} else {
+				relative_timeout = ast_samp2tv(props->atxfernoanswertimeout, 1000);
+			}
+
+			absolute_timeout = ast_tvadd(props->start, relative_timeout);
+			timeout_arg.tv_sec = absolute_timeout.tv_sec;
+			timeout_arg.tv_nsec = absolute_timeout.tv_usec * 1000;
 
 			if (ast_cond_timedwait(&props->cond, lock, &timeout_arg) == ETIMEDOUT) {
 				return STIMULUS_TIMEOUT;




More information about the asterisk-commits mailing list