[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