[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