aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--main/autoservice.c63
1 files changed, 38 insertions, 25 deletions
diff --git a/main/autoservice.c b/main/autoservice.c
index 853c1dfab..02aa713a4 100644
--- a/main/autoservice.c
+++ b/main/autoservice.c
@@ -51,6 +51,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;
};
@@ -151,42 +152,50 @@ int ast_autoservice_start(struct ast_channel *chan)
struct asent *as;
AST_RWLIST_WRLOCK(&aslist);
-
- /* Check if the channel already has autoservice */
AST_RWLIST_TRAVERSE(&aslist, as, list) {
if (as->chan == chan) {
as->use_count++;
break;
}
}
+ AST_RWLIST_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_RWLIST_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_RWLIST_REMOVE(&aslist, as, list);
- ast_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_RWLIST_WRLOCK(&aslist);
+ AST_RWLIST_INSERT_HEAD(&aslist, as, list);
AST_RWLIST_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_RWLIST_WRLOCK(&aslist);
+ AST_RWLIST_REMOVE(&aslist, as, list);
+ AST_RWLIST_UNLOCK(&aslist);
+ free(as);
+ res = -1;
+ } else
+ pthread_kill(asthread, SIGURG);
+ }
+
return res;
}
@@ -197,6 +206,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);
@@ -208,11 +218,11 @@ int ast_autoservice_stop(struct ast_channel *chan)
if (as->use_count)
break;
AST_LIST_APPEND_LIST(&dtmf_frames, &as->dtmf_frames, frame_list);
+ orig_end_dtmf_flag = as->orig_end_dtmf_flag;
ast_free(as);
removed = 1;
if (!ast_check_hangup(chan))
res = 0;
- ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
break;
}
}
@@ -226,6 +236,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);