freetdm: add code to troubleshoot crash on tone generation

This commit is contained in:
Moises Silva 2011-02-09 13:26:23 -05:00
parent 0cbac4ad25
commit eeac03ef50
1 changed files with 39 additions and 9 deletions

View File

@ -2743,10 +2743,9 @@ static ftdm_status_t ftdmchan_activate_dtmf_buffer(ftdm_channel_t *ftdmchan)
if (!ftdmchan->dtmf_buffer) {
if (ftdm_buffer_create(&ftdmchan->dtmf_buffer, 1024, 3192, 0) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Failed to allocate DTMF Buffer!\n");
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "buffer error");
return FTDM_FAIL;
} else {
ftdm_log(FTDM_LOG_DEBUG, "Created DTMF Buffer!\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Created DTMF buffer\n");
}
}
@ -3588,8 +3587,17 @@ static FIO_READ_FUNCTION(ftdm_raw_read)
return status;
}
static ftdm_status_t handle_dtmf(ftdm_channel_t *ftdmchan, ftdm_size_t datalen)
/* This function takes care of automatically generating DTMF or FSK tones when needed */
static ftdm_status_t handle_tone_generation(ftdm_channel_t *ftdmchan, ftdm_size_t datalen)
{
/*
* datalen: size in bytes of the chunk of data the user requested to read (this function
* is called from the ftdm_channel_read function)
* dblen: size currently in use in any of the tone generation buffers (data available in the buffer)
* gen_dtmf_buffer: buffer holding the raw ASCII digits that the user requested to generate
* dtmf_buffer: raw linear tone data generated by teletone to be written to the devices
* fsk_buffer: raw linear FSK modulated data for caller id
*/
ftdm_buffer_t *buffer = NULL;
ftdm_size_t dblen = 0;
int wrote = 0;
@ -3604,7 +3612,7 @@ static ftdm_status_t handle_dtmf(ftdm_channel_t *ftdmchan, ftdm_size_t datalen)
}
if (ftdm_buffer_read(ftdmchan->gen_dtmf_buffer, digits, dblen) && !ftdm_strlen_zero_buf(digits)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generating DTMF [%s]\n", digits);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generating DTMF [%s]\n", digits);
cur = digits;
@ -3618,7 +3626,7 @@ static ftdm_status_t handle_dtmf(ftdm_channel_t *ftdmchan, ftdm_size_t datalen)
ftdm_buffer_write(ftdmchan->dtmf_buffer, ftdmchan->tone_session.buffer, wrote * 2);
x++;
} else {
ftdm_log(FTDM_LOG_ERROR, "%d:%d Problem Adding DTMF SEQ [%s]\n", ftdmchan->span_id, ftdmchan->chan_id, digits);
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Problem adding DTMF sequence [%s]\n", digits);
return FTDM_FAIL;
}
}
@ -3631,6 +3639,7 @@ static ftdm_status_t handle_dtmf(ftdm_channel_t *ftdmchan, ftdm_size_t datalen)
if (!ftdmchan->buffer_delay || --ftdmchan->buffer_delay == 0) {
/* time to pick a buffer, either the dtmf or fsk buffer */
if (ftdmchan->dtmf_buffer && (dblen = ftdm_buffer_inuse(ftdmchan->dtmf_buffer))) {
buffer = ftdmchan->dtmf_buffer;
} else if (ftdmchan->fsk_buffer && (dblen = ftdm_buffer_inuse(ftdmchan->fsk_buffer))) {
@ -3638,22 +3647,41 @@ static ftdm_status_t handle_dtmf(ftdm_channel_t *ftdmchan, ftdm_size_t datalen)
}
}
/* if we picked a buffer, time to read from it and write the linear data to the device */
if (buffer) {
ftdm_size_t dlen = datalen;
uint8_t auxbuf[1024];
/* we initialize dlen to datalen, which is the size in bytes the
* user wants to read (typically chunks of 160 bytes, 20ms G.711) */
ftdm_size_t dlen = datalen;
ftdm_size_t len, br, max = sizeof(auxbuf);
/* if the codec is not linear, then data is really twice as much cuz
tone generation is done in linear (we assume anything different than linear is G.711) */
if (ftdmchan->native_codec != FTDM_CODEC_SLIN) {
dlen *= 2;
}
/* we do not expect the user chunks to be bigger than auxbuf */
ftdm_assert(dlen <= sizeof(auxbuf), "Unexpected size for user data chunk size\n");
/* dblen is the size in use for dtmf_buffer or fsk_buffer, and dlen is the size
* of the read chunks of the user, we pick the smaller one */
len = dblen > dlen ? dlen : dblen;
/* we can't read more than the size of our auxiliary buffer */
ftdm_assert((len <= sizeof(auxbuf)), "Unexpected size to read into auxbuf\n");
br = ftdm_buffer_read(buffer, auxbuf, len);
/* the amount read can't possibly be bigger than what we requested */
ftdm_assert((br <= len), "Unexpected size read from tone generation buffer\n");
/* if we read less than the chunk size, we must fill in with silence the rest */
if (br < dlen) {
memset(auxbuf + br, 0, dlen - br);
}
/* finally we convert to the native format for the channel if necessary */
if (ftdmchan->native_codec != FTDM_CODEC_SLIN) {
if (ftdmchan->native_codec == FTDM_CODEC_ULAW) {
fio_slin2ulaw(auxbuf, max, &dlen);
@ -3662,6 +3690,7 @@ static ftdm_status_t handle_dtmf(ftdm_channel_t *ftdmchan, ftdm_size_t datalen)
}
}
/* write the tone to the channel */
return ftdm_raw_write(ftdmchan, auxbuf, &dlen);
}
@ -3741,7 +3770,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data
rdata[i] = ftdmchan->rxgain_table[rdata[i]];
}
}
handle_dtmf(ftdmchan, *datalen);
handle_tone_generation(ftdmchan, *datalen);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE) && ftdmchan->effective_codec != ftdmchan->native_codec) {
if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
@ -3938,7 +3967,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat
if (!ftdmchan->buffer_delay &&
((ftdmchan->dtmf_buffer && ftdm_buffer_inuse(ftdmchan->dtmf_buffer)) ||
(ftdmchan->fsk_buffer && ftdm_buffer_inuse(ftdmchan->fsk_buffer)))) {
/* read size writing DTMF ATM */
/* generating some kind of tone at the moment (see handle_tone_generation),
* we ignore user data ... */
goto done;
}