aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-12-26 19:04:31 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-12-26 19:04:31 +0000
commita32e16463c51393eea3f59f0458372a34b4ce2b8 (patch)
tree93722e171e5798aebfeaebff69139751379d2dc1
parent79bb594590a5cb52d280c2d86570196a4876c33b (diff)
Just in case the AST_FLAG_END_DTMF_ONLY flag was already set before starting
autoservice, remember it and ensure that the channel has the same setting when autoservice gets stopped. (pointed out by d1mas, patched up by me) git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@94801 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--main/autoservice.c64
1 files changed, 39 insertions, 25 deletions
diff --git a/main/autoservice.c b/main/autoservice.c
index 9caa56508..fe4e2a705 100644
--- a/main/autoservice.c
+++ b/main/autoservice.c
@@ -58,6 +58,7 @@ struct asent {
* channel. It will ensure that it doesn't actually get stopped until
* it gets stopped for the last time. */
unsigned int use_count;
+ unsigned int orig_end_dtmf_flag:1;
AST_LIST_HEAD_NOLOCK(, ast_frame) dtmf_frames;
AST_LIST_ENTRY(asent) list;
};
@@ -157,43 +158,52 @@ int ast_autoservice_start(struct ast_channel *chan)
int res = 0;
struct asent *as;
- AST_LIST_LOCK(&aslist);
-
/* Check if the channel already has autoservice */
+ AST_LIST_LOCK(&aslist);
AST_LIST_TRAVERSE(&aslist, as, list) {
if (as->chan == chan) {
as->use_count++;
break;
}
}
+ AST_LIST_UNLOCK(&aslist);
- /* If not, start autoservice on channel */
if (as) {
- /* Entry extist, autoservice is already handling this channel */
- } else if ((as = ast_calloc(1, sizeof(*as))) == NULL) {
- /* Memory allocation failed */
- res = -1;
- } else {
- /* New entry created */
- as->chan = chan;
- ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
- as->use_count = 1;
- AST_LIST_INSERT_HEAD(&aslist, as, list);
- if (asthread == AST_PTHREADT_NULL) { /* need start the thread */
- if (ast_pthread_create_background(&asthread, NULL, autoservice_run, NULL)) {
- ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n");
- /* There will only be a single member in the list at this point,
- the one we just added. */
- AST_LIST_REMOVE(&aslist, as, list);
- free(as);
- res = -1;
- } else
- pthread_kill(asthread, SIGURG);
- }
+ /* Entry exists, autoservice is already handling this channel */
+ return 0;
}
+ if (!(as = ast_calloc(1, sizeof(*as))))
+ return -1;
+
+ /* New entry created */
+ as->chan = chan;
+ as->use_count = 1;
+
+ ast_channel_lock(chan);
+ as->orig_end_dtmf_flag = ast_test_flag(chan, AST_FLAG_END_DTMF_ONLY) ? 1 : 0;
+ if (!as->orig_end_dtmf_flag)
+ ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
+ ast_channel_unlock(chan);
+
+ AST_LIST_LOCK(&aslist);
+ AST_LIST_INSERT_HEAD(&aslist, as, list);
AST_LIST_UNLOCK(&aslist);
+ if (asthread == AST_PTHREADT_NULL) { /* need start the thread */
+ if (ast_pthread_create_background(&asthread, NULL, autoservice_run, NULL)) {
+ ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n");
+ /* There will only be a single member in the list at this point,
+ the one we just added. */
+ AST_LIST_LOCK(&aslist);
+ AST_LIST_REMOVE(&aslist, as, list);
+ AST_LIST_UNLOCK(&aslist);
+ free(as);
+ res = -1;
+ } else
+ pthread_kill(asthread, SIGURG);
+ }
+
return res;
}
@@ -204,6 +214,7 @@ int ast_autoservice_stop(struct ast_channel *chan)
AST_LIST_HEAD_NOLOCK(, ast_frame) dtmf_frames;
struct ast_frame *f;
int removed = 0;
+ int orig_end_dtmf_flag = 0;
AST_LIST_HEAD_INIT_NOLOCK(&dtmf_frames);
@@ -215,11 +226,11 @@ int ast_autoservice_stop(struct ast_channel *chan)
break;
AST_LIST_REMOVE_CURRENT(&aslist, list);
AST_LIST_APPEND_LIST(&dtmf_frames, &as->dtmf_frames, frame_list);
+ orig_end_dtmf_flag = as->orig_end_dtmf_flag;
free(as);
removed = 1;
if (!chan->_softhangup)
res = 0;
- ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
break;
}
}
@@ -233,6 +244,9 @@ int ast_autoservice_stop(struct ast_channel *chan)
if (!removed)
return 0;
+ if (!orig_end_dtmf_flag)
+ ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
+
/* Wait for it to un-block */
while (ast_test_flag(chan, AST_FLAG_BLOCKING))
usleep(1000);