[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