summaryrefslogtreecommitdiff
path: root/channels/chan_dahdi.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2015-08-05 14:21:50 -0500
committerRichard Mudgett <rmudgett@digium.com>2015-08-11 16:58:11 -0500
commitb9b957d4e921a78b0918b584cb6e3d9a34abc160 (patch)
tree7c2f3be797171773bdcd87a21f011f7cb6911a35 /channels/chan_dahdi.c
parente188192ad10a8570785986a46666b91d7a448b75 (diff)
chan_dahdi.c: Lock private struct for ast_write().
There is a window of opportunity for DTMF to not go out if an audio frame is in the process of being written to DAHDI while another thread starts sending DTMF. The thread sending the audio frame could be past the currently dialing check before being preempted by another thread starting a DTMF generation request. When the thread sending the audio frame resumes it will then cause DAHDI to stop the DTMF tone generation. The result is no DTMF goes out. * Made dahdi_write() lock the private struct before writing to the DAHDI file descriptor. ASTERISK-25315 Reported by John Hardin Change-Id: Ib4e0264cf63305ed5da701188447668e72ec9abb
Diffstat (limited to 'channels/chan_dahdi.c')
-rw-r--r--channels/chan_dahdi.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index fe613097c..b854c7342 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -8772,39 +8772,52 @@ static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int
static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
{
- struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
+ struct dahdi_pvt *p;
int res;
int idx;
+
+ /* Write a frame of (presumably voice) data */
+ if (frame->frametype != AST_FRAME_VOICE) {
+ if (frame->frametype != AST_FRAME_IMAGE) {
+ ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n",
+ frame->frametype);
+ }
+ return 0;
+ }
+
+ /* Return if it's not valid data */
+ if (!frame->data.ptr || !frame->datalen) {
+ return 0;
+ }
+
+ p = ast_channel_tech_pvt(ast);
+ ast_mutex_lock(&p->lock);
+
idx = dahdi_get_index(ast, p, 0);
if (idx < 0) {
+ ast_mutex_unlock(&p->lock);
ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
return -1;
}
- /* Write a frame of (presumably voice) data */
- if (frame->frametype != AST_FRAME_VOICE) {
- if (frame->frametype != AST_FRAME_IMAGE)
- ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype);
- return 0;
- }
if (p->dialing) {
+ ast_mutex_unlock(&p->lock);
ast_debug(5, "Dropping frame since I'm still dialing on %s...\n",
ast_channel_name(ast));
return 0;
}
if (!p->owner) {
+ ast_mutex_unlock(&p->lock);
ast_debug(5, "Dropping frame since there is no active owner on %s...\n",
ast_channel_name(ast));
return 0;
}
if (p->cidspill) {
+ ast_mutex_unlock(&p->lock);
ast_debug(5, "Dropping frame since I've still got a callerid spill on %s...\n",
ast_channel_name(ast));
return 0;
}
- /* Return if it's not valid data */
- if (!frame->data.ptr || !frame->datalen)
- return 0;
if (ast_format_cmp(frame->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
if (!p->subs[idx].linear) {
@@ -8825,10 +8838,12 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
}
res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
} else {
+ ast_mutex_unlock(&p->lock);
ast_log(LOG_WARNING, "Cannot handle frames in %s format\n",
ast_format_get_name(frame->subclass.format));
return -1;
}
+ ast_mutex_unlock(&p->lock);
if (res < 0) {
ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
return -1;