aboutsummaryrefslogtreecommitdiffstats
path: root/apps/app_dial.c
diff options
context:
space:
mode:
authormurf <murf@f38db490-d61c-443f-a65b-d21fe96a405b>2008-10-29 05:09:20 +0000
committermurf <murf@f38db490-d61c-443f-a65b-d21fe96a405b>2008-10-29 05:09:20 +0000
commit6040ddc2e90c1d8a95fa7583916c20ffbcc74951 (patch)
treedc1493103568a474a7e7d39c378faf5b430d3d97 /apps/app_dial.c
parentca111a5c9590791ee0443e4c82364017e19b634f (diff)
Merged revisions 152536 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ................ r152536 | murf | 2008-10-28 23:01:00 -0600 (Tue, 28 Oct 2008) | 57 lines Merged revisions 152535 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r152535 | murf | 2008-10-28 22:36:32 -0600 (Tue, 28 Oct 2008) | 46 lines The magic trick to avoid this crash is not to try to find the channel by name in the list, which is slow and resource consuming, but rather to pay attention to the result codes from the ast_bridge_call, to which I added the AST_PBX_NO_HANGUP_PEER_PARKED value, which now are returned when a channel is parked. Why? because CDR's aren't generated via parking, so nothing is needed, but if a transfer occurred, there are critical things I need. If you get AST_PBX_KEEPALIVE, then don't touch the channel pointer. If you get AST_PBX_NO_HANGUP_PEER, or AST_PBX_NO_HANGUP_PEER_PARKED, then don't touch the peer pointer. Updated the several places where the results from a bridge were not being properly obeyed, and fixed some code I had introduced so that the results of the bridge were not overridden (in trunk). All the places that previously tested for AST_PBX_NO_HANGUP_PEER now have to check for both AST_PBX_NO_HANGUP_PEER and AST_PBX_NO_HANGUP_PEER_PARKED. I tested this against the 4 common parking scenarios: 1. A calls B; B answers; A parks B; B hangs up while A is getting the parking slot announcement, immediately after being put on hold. 2. A calls B; B answers; A parks B; B hangs up after A has been hung up, but before the park times out. 3. A calls B; B answers; B parks A; A hangs up while B is getting the parking slot announcement, immediately after being put on hold. 4. A calls B; B answers; B parks A; A hangs up after B has been hung up, but before the park times out. No crash. I also ran the scenarios above against valgrind, and accesses looked good. ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.1@152537 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps/app_dial.c')
-rw-r--r--apps/app_dial.c93
1 files changed, 51 insertions, 42 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c
index de28e1bb1..777e4830e 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 1999 - 2006, Digium, Inc.
+ * Copyright (C) 1999 - 2008, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
@@ -111,7 +111,8 @@ static char *descrip =
" DTMF string is sent to the called party, and the 'calling' DTMF\n"
" string is sent to the calling party. Both parameters can be used\n"
" alone.\n"
-" e - execute the 'h' extension for peer after the call ends\n"
+" e - execute the 'h' extension for peer after the call ends. This\n"
+" operation will not be performed if the peer was parked\n"
" f - Force the callerid of the *calling* channel to be set as the\n"
" extension associated with the channel using a dialplan 'hint'.\n"
" For example, some PSTNs do not allow CallerID to be set to anything\n"
@@ -1793,16 +1794,17 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
struct ast_app *theapp;
const char *gosub_result;
char *gosub_args, *gosub_argstart;
+ int res9 = -1;
- res = ast_autoservice_start(chan);
- if (res) {
+ res9 = ast_autoservice_start(chan);
+ if (res9) {
ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
- res = -1;
+ res9 = -1;
}
theapp = pbx_findapp("Gosub");
- if (theapp && !res) {
+ if (theapp && !res9) {
replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GOSUB]);
/* Set where we came from */
@@ -1820,50 +1822,50 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
}
if (gosub_args) {
- res = pbx_exec(peer, theapp, gosub_args);
+ res9 = pbx_exec(peer, theapp, gosub_args);
ast_pbx_run(peer);
ast_free(gosub_args);
if (option_debug)
- ast_log(LOG_DEBUG, "Gosub exited with status %d\n", res);
+ ast_log(LOG_DEBUG, "Gosub exited with status %d\n", res9);
} else
ast_log(LOG_ERROR, "Could not Allocate string for Gosub arguments -- Gosub Call Aborted!\n");
- res = 0;
- } else if (!res) {
+ res9 = 0;
+ } else if (!res9) {
ast_log(LOG_ERROR, "Could not find application Gosub\n");
- res = -1;
+ res9 = -1;
}
if (ast_autoservice_stop(chan) < 0) {
ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
- res = -1;
+ res9 = -1;
}
ast_channel_lock(peer);
- if (!res && (gosub_result = pbx_builtin_getvar_helper(peer, "GOSUB_RESULT"))) {
+ if (!res9 && (gosub_result = pbx_builtin_getvar_helper(peer, "GOSUB_RESULT"))) {
char *gosub_transfer_dest;
if (!strcasecmp(gosub_result, "BUSY")) {
ast_copy_string(pa.status, gosub_result, sizeof(pa.status));
ast_set_flag64(peerflags, OPT_GO_ON);
- res = -1;
+ res9 = -1;
} else if (!strcasecmp(gosub_result, "CONGESTION") || !strcasecmp(gosub_result, "CHANUNAVAIL")) {
ast_copy_string(pa.status, gosub_result, sizeof(pa.status));
ast_set_flag64(peerflags, OPT_GO_ON);
- res = -1;
+ res9 = -1;
} else if (!strcasecmp(gosub_result, "CONTINUE")) {
/* hangup peer and keep chan alive assuming the macro has changed
the context / exten / priority or perhaps
the next priority in the current exten is desired.
*/
ast_set_flag64(peerflags, OPT_GO_ON);
- res = -1;
+ res9 = -1;
} else if (!strcasecmp(gosub_result, "ABORT")) {
/* Hangup both ends unless the caller has the g flag */
- res = -1;
+ res9 = -1;
} else if (!strncasecmp(gosub_result, "GOTO:", 5) && (gosub_transfer_dest = ast_strdupa(gosub_result + 5))) {
- res = -1;
+ res9 = -1;
/* perform a transfer to a new extension */
if (strchr(gosub_transfer_dest, '^')) { /* context^exten^priority*/
replace_macro_delimiter(gosub_transfer_dest);
@@ -1956,32 +1958,34 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
- if (ast_test_flag64(&opts, OPT_PEER_H)) {
+ if (res != AST_PBX_NO_HANGUP_PEER_PARKED && ast_test_flag64(&opts, OPT_PEER_H)) {
ast_log(LOG_NOTICE, "PEER context: %s; PEER exten: %s; PEER priority: %d\n",
peer->context, peer->exten, peer->priority);
}
+ if (res != AST_PBX_NO_HANGUP_PEER_PARKED)
+ strcpy(peer->context, chan->context);
- strcpy(peer->context, chan->context);
-
- if (ast_test_flag64(&opts, OPT_PEER_H) && ast_exists_extension(peer, peer->context, "h", 1, peer->cid.cid_num)) {
+ if (res != AST_PBX_NO_HANGUP_PEER_PARKED && ast_test_flag64(&opts, OPT_PEER_H) && ast_exists_extension(peer, peer->context, "h", 1, peer->cid.cid_num)) {
int autoloopflag;
int found;
+ int res9;
+
strcpy(peer->exten, "h");
peer->priority = 1;
autoloopflag = ast_test_flag(peer, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */
ast_set_flag(peer, AST_FLAG_IN_AUTOLOOP);
- while ((res = ast_spawn_extension(peer, peer->context, peer->exten, peer->priority, peer->cid.cid_num, &found, 1)) == 0)
+ while ((res9 = ast_spawn_extension(peer, peer->context, peer->exten, peer->priority, peer->cid.cid_num, &found, 1)) == 0)
peer->priority++;
- if (found && res) {
+ if (found && res9) {
/* Something bad happened, or a hangup has been requested. */
ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
}
ast_set2_flag(peer, autoloopflag, AST_FLAG_IN_AUTOLOOP); /* set it back the way it was */
}
- if (res != AST_PBX_NO_HANGUP_PEER) {
+ if (res != AST_PBX_NO_HANGUP_PEER && res != AST_PBX_NO_HANGUP_PEER_PARKED) {
if (!ast_check_hangup(peer) && ast_test_flag64(&opts, OPT_CALLEE_GO_ON) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) {
replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]);
ast_parseable_goto(peer, opt_args[OPT_ARG_CALLEE_GO_ON]);
@@ -1994,23 +1998,28 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
}
}
out:
- if (moh) {
- moh = 0;
- ast_moh_stop(chan);
- } else if (sentringing) {
- sentringing = 0;
- ast_indicate(chan, -1);
- }
- ast_channel_early_bridge(chan, NULL);
- hanguptree(outgoing, NULL, 0); /* In this case, there's no answer anywhere */
- pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
- senddialendevent(chan, pa.status);
- ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status);
-
- if ((ast_test_flag64(peerflags, OPT_GO_ON)) && !ast_check_hangup(chan) && (res != AST_PBX_KEEPALIVE) && (res != AST_PBX_INCOMPLETE)) {
- if (calldurationlimit)
- memset(&chan->whentohangup, 0, sizeof(chan->whentohangup));
- res = 0;
+ /* cleaning up chan is not a good idea here if AST_PBX_KEEPALIVE
+ is returned; chan will get the love it needs from another
+ thread */
+ if (res != AST_PBX_KEEPALIVE) {
+ if (moh) {
+ moh = 0;
+ ast_moh_stop(chan);
+ } else if (sentringing) {
+ sentringing = 0;
+ ast_indicate(chan, -1);
+ }
+ ast_channel_early_bridge(chan, NULL);
+ hanguptree(outgoing, NULL, 0); /* In this case, there's no answer anywhere */
+ pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
+ senddialendevent(chan, pa.status);
+ ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status);
+
+ if ((ast_test_flag64(peerflags, OPT_GO_ON)) && !ast_check_hangup(chan) && (res != AST_PBX_KEEPALIVE) && (res != AST_PBX_INCOMPLETE)) {
+ if (calldurationlimit)
+ memset(&chan->whentohangup, 0, sizeof(chan->whentohangup));
+ res = 0;
+ }
}
done: