diff --git a/channels/chan_local.c b/channels/chan_local.c index b0e51f90df..e0c7431371 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -160,7 +160,8 @@ static struct local_pvt *local_pvt_destroy(struct local_pvt *pvt) return NULL; } -static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_frame *f, struct ast_channel *us) +static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_frame *f, + struct ast_channel *us, int us_locked) { struct ast_channel *other = NULL; @@ -184,11 +185,13 @@ static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_fra /* Ensure that we have both channels locked */ while (other && ast_channel_trylock(other)) { ast_mutex_unlock(&p->lock); - if (us) + if (us && us_locked) { ast_channel_unlock(us); + } usleep(1); - if (us) + if (us && us_locked) { ast_channel_lock(us); + } ast_mutex_lock(&p->lock); other = isoutbound ? p->owner : p->chan; } @@ -217,7 +220,7 @@ static int local_answer(struct ast_channel *ast) if (isoutbound) { /* Pass along answer since somebody answered us */ struct ast_frame answer = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER }; - res = local_queue_frame(p, isoutbound, &answer, ast); + res = local_queue_frame(p, isoutbound, &answer, ast, 1); } else ast_log(LOG_WARNING, "Huh? Local is being asked to answer?\n"); if (!res) @@ -306,7 +309,7 @@ static int local_write(struct ast_channel *ast, struct ast_frame *f) if (f && (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO)) check_bridge(p, isoutbound); if (!ast_test_flag(p, LOCAL_ALREADY_MASQED)) - res = local_queue_frame(p, isoutbound, f, ast); + res = local_queue_frame(p, isoutbound, f, ast, 1); else { if (option_debug) ast_log(LOG_DEBUG, "Not posting to queue since already masked on '%s'\n", ast->name); @@ -361,7 +364,7 @@ static int local_indicate(struct ast_channel *ast, int condition, const void *da f.subclass = condition; f.data = (void*)data; f.datalen = datalen; - if (!(res = local_queue_frame(p, isoutbound, &f, ast))) + if (!(res = local_queue_frame(p, isoutbound, &f, ast, 1))) ast_mutex_unlock(&p->lock); } @@ -381,7 +384,7 @@ static int local_digit_begin(struct ast_channel *ast, char digit) ast_mutex_lock(&p->lock); isoutbound = IS_OUTBOUND(ast, p); f.subclass = digit; - if (!(res = local_queue_frame(p, isoutbound, &f, ast))) + if (!(res = local_queue_frame(p, isoutbound, &f, ast, 0))) ast_mutex_unlock(&p->lock); return res; @@ -401,7 +404,7 @@ static int local_digit_end(struct ast_channel *ast, char digit, unsigned int dur isoutbound = IS_OUTBOUND(ast, p); f.subclass = digit; f.len = duration; - if (!(res = local_queue_frame(p, isoutbound, &f, ast))) + if (!(res = local_queue_frame(p, isoutbound, &f, ast, 0))) ast_mutex_unlock(&p->lock); return res; @@ -421,7 +424,7 @@ static int local_sendtext(struct ast_channel *ast, const char *text) isoutbound = IS_OUTBOUND(ast, p); f.data = (char *) text; f.datalen = strlen(text) + 1; - if (!(res = local_queue_frame(p, isoutbound, &f, ast))) + if (!(res = local_queue_frame(p, isoutbound, &f, ast, 0))) ast_mutex_unlock(&p->lock); return res; } @@ -441,7 +444,7 @@ static int local_sendhtml(struct ast_channel *ast, int subclass, const char *dat f.subclass = subclass; f.data = (char *)data; f.datalen = datalen; - if (!(res = local_queue_frame(p, isoutbound, &f, ast))) + if (!(res = local_queue_frame(p, isoutbound, &f, ast, 0))) ast_mutex_unlock(&p->lock); return res; } @@ -564,7 +567,7 @@ static int local_hangup(struct ast_channel *ast) /* Need to actually hangup since there is no PBX */ ochan = p->chan; else - res = local_queue_frame(p, isoutbound, &f, NULL); + res = local_queue_frame(p, isoutbound, &f, NULL, 1); if (!res) ast_mutex_unlock(&p->lock); if (ochan)