Merge remote-tracking branch 'fsorig/master'

Conflicts:
	src/mod/endpoints/mod_sofia/mod_sofia.c
	src/mod/endpoints/mod_sofia/sofia_glue.c
This commit is contained in:
Moises Silva committed 2011-09-28 12:19:48 -04:00
commit b004bcfc6d
407 files changed
+25813 -41133

No files matched your search

+25 -4
View File
@@ -6,7 +6,7 @@ int main(int argc, char *argv[])
int fd, b;
short sln[512] = {0};
teletone_dtmf_detect_state_t dtmf_detect = {0};
char digit_str[128] = "";
teletone_hit_type_t hit;
if (argc < 2) {
fprintf(stderr, "Arg Error!\n");
@@ -21,10 +21,31 @@ int main(int argc, char *argv[])
}
while((b = read(fd, sln, 320)) > 0) {
char digit_char;
unsigned int dur;
teletone_dtmf_detect(&dtmf_detect, sln, b / 2);
teletone_dtmf_get(&dtmf_detect, digit_str, sizeof(digit_str));
if (*digit_str) {
printf("digit: %s\n", digit_str);
if ((hit = teletone_dtmf_get(&dtmf_detect, &digit_char, &dur))) {
const char *hs = NULL;
switch(hit) {
case TT_HIT_BEGIN:
hs = "begin";
break;
case TT_HIT_MIDDLE:
hs = "middle";
break;
case TT_HIT_END:
hs = "end";
break;
default:
break;
}
printf("%s digit: %c\n", hs, digit_char);
}
}
close(fd);
+28 -15
View File
@@ -649,9 +649,6 @@ static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span)
if (span->fio->span_destroy(span) != FTDM_SUCCESS) {
status = FTDM_FAIL;
}
ftdm_safe_free(span->type);
ftdm_safe_free(span->name);
ftdm_safe_free(span->dtmf_hangup);
}
/* destroy final basic resources of the span data structure */
@@ -1858,7 +1855,14 @@ static ftdm_status_t _ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm
goto done;
}
ftdm_mutex_lock(check->mutex);
ftdm_channel_lock(check);
if (ftdm_test_flag(check, FTDM_CHANNEL_OPEN)) {
/* let them know is already open, but return the channel anyway */
status = FTDM_EBUSY;
*ftdmchan = check;
goto unlockchan;
}
/* The following if's and gotos replace a big if (this || this || this || this) else { nothing; } */
@@ -1905,7 +1909,7 @@ openchan:
goto done;
unlockchan:
ftdm_mutex_unlock(check->mutex);
ftdm_channel_unlock(check);
done:
ftdm_mutex_unlock(globals.mutex);
@@ -3855,7 +3859,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v
uint8_t sln_buf[1024] = {0};
int16_t *sln;
ftdm_size_t slen = 0;
char digit_str[80] = "";
if (ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
sln = data;
@@ -3956,13 +3959,18 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT) && !ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen);
teletone_dtmf_get(&ftdmchan->dtmf_detect, digit_str, sizeof(digit_str));
teletone_hit_type_t hit;
char digit_char;
uint32_t dur;
if(*digit_str) {
if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (*digit_str == 'D' || *digit_str == 'A')) {
if ((hit = teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen)) == TT_HIT_END) {
teletone_dtmf_get(&ftdmchan->dtmf_detect, &digit_char, &dur);
if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (digit_char == 'D' || digit_char == 'A')) {
ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK]++;
} else {
char digit_str[2] = { digit_char, 0};
if (!ftdmchan->span->sig_dtmf || (ftdmchan->span->sig_dtmf(ftdmchan, (const char*)digit_str) != FTDM_BREAK)) {
ftdm_channel_queue_dtmf(ftdmchan, digit_str);
}
@@ -4568,7 +4576,7 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const
*configured = 0;
*configured = span->fio->configure_span(span, str, chan_config->type, chan_config->name, chan_config->number);
if (!*configured) {
ftdm_log(FTDM_LOG_ERROR, "%d:Failed to configure span", span->span_id);
ftdm_log(FTDM_LOG_ERROR, "%d:Failed to configure span\n", span->span_id);
return FTDM_FAIL;
}
@@ -5468,10 +5476,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
if (sigmsg->channel) {
fchan = sigmsg->channel;
ftdm_channel_lock(fchan);
sigmsg->chan_id = fchan->chan_id;
sigmsg->span_id = fchan->span_id;
sigmsg->call_id = fchan->caller_data.call_id;
sigmsg->call_priv = fchan->caller_data.priv;
}
/* some core things to do on special events */
@@ -5561,6 +5565,14 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
}
if (fchan) {
/* set members of the sigmsg that must be present for all events */
sigmsg->chan_id = fchan->chan_id;
sigmsg->span_id = fchan->span_id;
sigmsg->call_id = fchan->caller_data.call_id;
sigmsg->call_priv = fchan->caller_data.priv;
}
/* if the signaling module uses a queue for signaling notifications, then enqueue it */
if (ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) {
ftdm_span_queue_signal(span, sigmsg);
@@ -5774,6 +5786,7 @@ FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void)
}
hashtable_remove(globals.span_hash, (void *)cur_span->name);
ftdm_safe_free(cur_span->dtmf_hangup);
ftdm_safe_free(cur_span->type);
ftdm_safe_free(cur_span->name);
ftdm_safe_free(cur_span);
@@ -39,7 +39,8 @@ typedef enum {
FTDM_ANALOG_RUNNING = (1 << 0),
FTDM_ANALOG_CALLERID = (1 << 1),
FTDM_ANALOG_ANSWER_POLARITY_REVERSE = (1 << 2),
FTDM_ANALOG_HANGUP_POLARITY_REVERSE = (1 << 3)
FTDM_ANALOG_HANGUP_POLARITY_REVERSE = (1 << 3),
FTDM_ANALOG_POLARITY_CALLERID = (1 << 4)
} ftdm_analog_flag_t;
#define FTDM_MAX_HOTLINE_STR 20
@@ -275,6 +275,15 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
break;
}
hotline = val;
} else if (!strcasecmp(var, "polarity_callerid")) {
if (!(val = va_arg(ap, char *))) {
break;
}
if (ftdm_true(val)) {
flags |= FTDM_ANALOG_POLARITY_CALLERID;
} else {
flags &= ~FTDM_ANALOG_POLARITY_CALLERID;
}
} else {
ftdm_log(FTDM_LOG_ERROR, "Unknown parameter %s in span %s\n", var, span->name);
}
@@ -1130,8 +1139,18 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
break;
}
if (event->channel->state == FTDM_CHANNEL_STATE_DOWN) {
ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG,
"Ignoring polarity reversal because this channel is down\n");
if (ftdm_test_flag(analog_data, FTDM_ANALOG_CALLERID)
&& ftdm_test_flag(analog_data, FTDM_ANALOG_POLARITY_CALLERID)) {
ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG, "Polarity reversal detected while down, getting caller id now\n");
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID);
event->channel->ring_count = 1;
ftdm_mutex_unlock(event->channel->mutex);
locked = 0;
ftdm_thread_create_detached(ftdm_analog_channel_run, event->channel);
} else {
ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG,
"Ignoring polarity reversal because this channel is down\n");
}
break;
}
/* we have a good channel, set the polarity flag and let the channel thread deal with it */
@@ -204,6 +204,32 @@ static int parse_debug(const char *in, uint32_t *flags)
return res;
}
/**
* \brief Parses a change status string to flags
* \param in change status string to parse for
* \return Flags
*/
static int parse_change_status(const char *in)
{
int flags = 0;
if (!in) {
return 0;
}
if (strstr(in, "in_service") || strstr(in, "in")) {
flags = SERVICE_CHANGE_STATUS_INSERVICE;
}
if (strstr(in, "maintenance") || strstr(in, "maint")) {
flags = SERVICE_CHANGE_STATUS_MAINTENANCE;
}
if (strstr(in, "out_of_service") || strstr(in, "out")) {
flags = SERVICE_CHANGE_STATUS_OUTOFSERVICE;
}
return flags;
}
static int print_debug(uint32_t flags, char *tmp, const int size)
{
int offset = 0;
@@ -240,6 +266,9 @@ static ftdm_io_interface_t ftdm_libpri_interface;
static const char *ftdm_libpri_usage =
"Usage:\n"
"libpri kill <span>\n"
"libpri reset <span>\n"
"libpri restart <span> <channel/all>\n"
"libpri maintenance <span> <channel/all> <in/maint/out>\n"
"libpri debug <span> [all|none|flag,...flagN]\n"
"\n"
"Possible debug flags:\n"
@@ -339,8 +368,78 @@ static FIO_API_FUNCTION(ftdm_libpri_api)
goto done;
}
}
if (!strcasecmp(argv[0], "reset")) {
ftdm_span_t *span = NULL;
if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) {
ftdm_libpri_data_t *isdn_data = span->signal_data;
if (span->start != ftdm_libpri_start) {
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
goto done;
}
pri_restart(isdn_data->spri.pri);
stream->write_function(stream, "%s: +OK reset.\n", __FILE__);
goto done;
} else {
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
goto done;
}
}
if (!strcasecmp(argv[0], "restart") && argc == 3) {
ftdm_span_t *span = NULL;
if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) {
ftdm_libpri_data_t *isdn_data = span->signal_data;
if (span->start != ftdm_libpri_start) {
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
goto done;
}
if (!strcasecmp(argv[2], "all")) {
int j;
for(j = 1; j <= span->chan_count; j++) {
pri_reset(isdn_data->spri.pri, j);
ftdm_sleep(50);
}
} else {
pri_reset(isdn_data->spri.pri, atoi(argv[2]));
}
stream->write_function(stream, "%s: +OK restart set.\n", __FILE__);
goto done;
} else {
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
goto done;
}
}
if (!strcasecmp(argv[0], "maintenance") && argc > 3) {
ftdm_span_t *span = NULL;
if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) {
ftdm_libpri_data_t *isdn_data = span->signal_data;
if (span->start != ftdm_libpri_start) {
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
goto done;
}
if (!isdn_data->service_message_support) {
stream->write_function(stream, "%s: -ERR service message support is disabled\n", __FILE__);
goto done;
}
if (!strcasecmp(argv[2], "all")) {
int j;
for(j = 1; j <= span->chan_count; j++) {
pri_maintenance_service(isdn_data->spri.pri, atoi(argv[1]), j, parse_change_status(argv[3]));
ftdm_sleep(50);
}
} else {
pri_maintenance_service(isdn_data->spri.pri, atoi(argv[1]), atoi(argv[2]), parse_change_status(argv[3]));
}
stream->write_function(stream, "%s: +OK change status set.\n", __FILE__);
goto done;
} else {
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
goto done;
}
}
}
stream->write_function(stream, "%s: -ERR invalid command.\n", __FILE__);
done:
@@ -1780,6 +1879,10 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
pri_facility_enable(isdn_data->spri.pri);
}
#endif
/* Support the different switch of service status */
if (isdn_data->service_message_support) {
pri_set_service_message_support(isdn_data->spri.pri, 1 /* True */);
}
if (res == 0) {
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANY, on_anything);
@@ -1835,6 +1938,14 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
ftdm_sleep(5000);
}
out:
/* close d-channel, if set */
if (isdn_data->dchan) {
if (ftdm_channel_close(&isdn_data->dchan) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Failed to close D-Channel %d:%d\n",
ftdm_channel_get_span_id(isdn_data->dchan), ftdm_channel_get_id(isdn_data->dchan));
}
}
ftdm_log(FTDM_LOG_DEBUG, "PRI thread ended on span %d\n", ftdm_span_get_id(span));
ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
@@ -2159,6 +2270,11 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
isdn_data->debug_mask = 0;
}
}
else if (!strcasecmp(var, "service_message_support")) {
if (ftdm_true(val)) {
isdn_data->service_message_support = 1;
}
}
else {
ftdm_log(FTDM_LOG_ERROR, "Unknown parameter '%s', aborting configuration\n", var);
snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var);
@@ -31,6 +31,11 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
typedef enum {
SERVICE_CHANGE_STATUS_INSERVICE = 0,
SERVICE_CHANGE_STATUS_MAINTENANCE = 1,
SERVICE_CHANGE_STATUS_OUTOFSERVICE = 2
} service_change_status_t;
#ifndef FTMOD_LIBPRI_H
#define FTMOD_LIBPRI_H
@@ -69,6 +74,7 @@ struct ftdm_libpri_data {
int overlap; /*!< Overlap dial flags */
unsigned int layer1;
unsigned int ton;
unsigned int service_message_support;
lpwrap_pri_t spri;
};
File diff suppressed because it is too large. Load diff
@@ -69,6 +69,8 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad);
set_redir_num(ftdmchan, &conEvnt.redirNmb);
set_calling_name(ftdmchan, &conEvnt);
/* set_facility_ie will overwrite Calling Name for NI-2 if user specifies custom Facility IE */
set_facility_ie(ftdmchan, &conEvnt.facilityStr);
set_prog_ind_ie(ftdmchan, &conEvnt.progInd, prog_ind);
@@ -719,12 +719,19 @@ ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt)
} else {
switch (signal_data->switchtype) {
case SNGISDN_SWITCH_NI2:
/* TODO: Need to send the caller ID as a facility IE */
#ifdef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY
{
if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
sng_isdn_encode_facility_caller_name(caller_data->cid_name, conEvnt->facilityStr.facilityStr.val, &conEvnt->facilityStr.facilityStr.len);
conEvnt->facilityStr.eh.pres = PRSNT_NODEF;
conEvnt->facilityStr.facilityStr.pres = PRSNT_NODEF;
}
}
#endif
break;
case SNGISDN_SWITCH_EUROISDN:
if (signal_data->signalling != SNGISDN_SIGNALING_NET) {
break;
break;
}
/* follow through */
case SNGISDN_SWITCH_5ESS:
@@ -39,6 +39,11 @@
*
*/
#ifdef WP_DEBUG_IO
#define _BSD_SOURCE
#include <syscall.h>
#endif
#ifdef __sun
#include <unistd.h>
#include <stropts.h>
@@ -99,6 +104,17 @@ static struct {
uint32_t ring_off_ms;
} wp_globals;
typedef struct {
sangoma_wait_obj_t *waitobj;
#ifdef WP_DEBUG_IO
/* record the last reader threads */
pid_t readers[10];
int rindex;
ftdm_time_t last_read;
#endif
} wp_channel_t;
#define WP_GET_WAITABLE(fchan) ((wp_channel_t *)((fchan)->io_data))->waitobj
/* a bunch of this stuff should go into the wanpipe_tdm_api_iface.h */
FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event);
@@ -123,7 +139,7 @@ static __inline__ int tdmv_api_wait_socket(ftdm_channel_t *ftdmchan, int timeout
int err;
uint32_t inflags = *flags;
uint32_t outflags = 0;
sangoma_wait_obj_t *sangoma_wait_obj = ftdmchan->io_data;
sangoma_wait_obj_t *sangoma_wait_obj = WP_GET_WAITABLE(ftdmchan);
if (timeout == -1) {
timeout = SANGOMA_WAIT_INFINITE;
@@ -254,9 +270,13 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
}
if (ftdm_span_add_channel(span, sockfd, type, &chan) == FTDM_SUCCESS) {
wp_channel_t *wpchan = NULL;
wanpipe_tdm_api_t tdm_api;
memset(&tdm_api, 0, sizeof(tdm_api));
#ifdef LIBSANGOMA_VERSION
wpchan = ftdm_calloc(1, sizeof(*wpchan));
ftdm_assert(wpchan != NULL, "wpchan alloc failed\n");
chan->io_data = wpchan;
/* we need SANGOMA_DEVICE_WAIT_OBJ_SIG and not SANGOMA_DEVICE_WAIT_OBJ alone because we need to call
* sangoma_wait_obj_sig to wake up any I/O waiters when closing the channel (typically on ftdm shutdown)
* this adds an extra pair of file descriptors to the waitable object
@@ -266,7 +286,7 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
ftdm_log(FTDM_LOG_ERROR, "failure create waitable object for s%dc%d\n", spanno, x);
continue;
}
chan->io_data = sangoma_wait_obj;
WP_GET_WAITABLE(chan) = sangoma_wait_obj;
#endif
chan->physical_span_id = spanno;
@@ -580,9 +600,16 @@ static FIO_OPEN_FUNCTION(wanpipe_open)
static FIO_CLOSE_FUNCTION(wanpipe_close)
{
#ifdef LIBSANGOMA_VERSION
sangoma_wait_obj_t *waitobj = ftdmchan->io_data;
sangoma_wait_obj_t *waitobj = WP_GET_WAITABLE(ftdmchan);
/* kick any I/O waiters */
sangoma_wait_obj_signal(waitobj);
#ifdef WP_DEBUG_IO
{
wp_channel_t *wchan = ftdmchan->io_data;
memset(wchan->readers, 0, sizeof(wchan->readers));
wchan->rindex = 0;
}
#endif
#endif
return FTDM_SUCCESS;
}
@@ -950,10 +977,44 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx
static FIO_READ_FUNCTION(wanpipe_read)
{
int rx_len = 0;
int rq_len = (int)*datalen;
wp_tdm_api_rx_hdr_t hdrframe;
memset(&hdrframe, 0, sizeof(hdrframe));
#ifdef WP_DEBUG_IO
wp_channel_t *wchan = ftdmchan->io_data;
ftdm_time_t time_diff = 0;
pid_t previous_thread = 1;
pid_t current_thread = 0;
int previous_thread_index = 0;
previous_thread_index = wchan->rindex == 0 ? (ftdm_array_len(wchan->readers) - 1) : wchan->rindex - 1;
previous_thread = wchan->readers[previous_thread_index];
current_thread = syscall(SYS_gettid);
if (current_thread && current_thread != wchan->readers[wchan->rindex]) {
if (!wchan->readers[wchan->rindex]) {
wchan->readers[wchan->rindex] = current_thread;
/* first read */
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Initial reader thread is %d\n", current_thread);
previous_thread = current_thread;
} else {
previous_thread = wchan->readers[wchan->rindex];
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Changed reader thread from %d to %d (rindex = %d)\n",
previous_thread, current_thread, wchan->rindex);
if (wchan->rindex == (ftdm_array_len(wchan->readers) - 1)) {
wchan->rindex = 0;
} else {
wchan->rindex++;
}
wchan->readers[wchan->rindex] = current_thread;
}
}
ftdm_time_t curr = ftdm_current_time_in_ms();
if (wchan->last_read) {
time_diff = curr - wchan->last_read;
}
#endif
memset(&hdrframe, 0, sizeof(hdrframe));
rx_len = sangoma_readmsg_tdm(ftdmchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (int)*datalen, 0);
*datalen = rx_len;
@@ -963,14 +1024,20 @@ static FIO_READ_FUNCTION(wanpipe_read)
}
if (rx_len < 0) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno));
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read from sangoma device: %s (%d)\n", strerror(errno), rx_len);
#ifdef WP_DEBUG_IO
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read %d bytes from sangoma device: %s (%d) "
"(read time diff = %llums, prev thread = %d, curr thread = %d)\n", rq_len, strerror(errno), rx_len,
time_diff, previous_thread, current_thread);
#else
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read %d bytes from sangoma device: %s (%d)\n", rq_len, strerror(errno), rx_len);
#endif
return FTDM_FAIL;
}
if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) {
wanpipe_read_stats(ftdmchan, &hdrframe);
}
return FTDM_SUCCESS;
}
@@ -1116,7 +1183,7 @@ FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
if (!ftdmchan->io_data) {
continue; /* should never happen but happens when shutting down */
}
pfds[j] = ftdmchan->io_data;
pfds[j] = WP_GET_WAITABLE(ftdmchan);
inflags[j] = chan_events;
#else
memset(&pfds[j], 0, sizeof(pfds[j]));
@@ -1578,10 +1645,10 @@ static FIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
{
#ifdef LIBSANGOMA_VERSION
if (ftdmchan->io_data) {
sangoma_wait_obj_t *sangoma_wait_obj;
sangoma_wait_obj = ftdmchan->io_data;
ftdmchan->io_data = NULL;
sangoma_wait_obj_t *sangoma_wait_obj = WP_GET_WAITABLE(ftdmchan);
sangoma_wait_obj_delete(&sangoma_wait_obj);
ftdm_safe_free(ftdmchan->io_data);
ftdmchan->io_data = NULL;
}
#endif
@@ -1612,7 +1679,8 @@ static FIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
*/
static FIO_IO_LOAD_FUNCTION(wanpipe_init)
{
assert(fio != NULL);
ftdm_assert(fio != NULL, "fio should not be null\n");
memset(&wanpipe_interface, 0, sizeof(wanpipe_interface));
wp_globals.codec_ms = 20;
+24 -1
View File
@@ -29,6 +29,12 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
*
* Moises Silva <moy@sangoma.com>
* W McRoberts <fs@whmcr.com>
*
*/
#include "private/ftdm_core.h"
@@ -94,6 +100,7 @@ struct ioctl_codes {
ioctlcmd ECHOTRAIN;
ioctlcmd SETTXBITS;
ioctlcmd GETRXBITS;
ioctlcmd SETPOLARITY;
};
/**
@@ -169,7 +176,8 @@ static struct ioctl_codes dahdi_ioctl_codes = {
.GETCONFMUTE = DAHDI_GETCONFMUTE,
.ECHOTRAIN = DAHDI_ECHOTRAIN,
.SETTXBITS = DAHDI_SETTXBITS,
.GETRXBITS = DAHDI_GETRXBITS
.GETRXBITS = DAHDI_GETRXBITS,
.SETPOLARITY = DAHDI_SETPOLARITY
};
#define ZT_INVALID_SOCKET -1
@@ -826,6 +834,15 @@ static FIO_COMMAND_FUNCTION(zt_command)
err = ioctl(ftdmchan->sockfd, codes.FLUSH, &flushmode);
}
break;
case FTDM_COMMAND_SET_POLARITY:
{
ftdm_polarity_t polarity = FTDM_COMMAND_OBJ_INT;
err = ioctl(ftdmchan->sockfd, codes.SETPOLARITY, polarity);
if (!err) {
ftdmchan->polarity = polarity;
}
}
break;
case FTDM_COMMAND_FLUSH_RX_BUFFERS:
{
int flushmode = ZT_FLUSH_READ;
@@ -1088,6 +1105,12 @@ static __inline__ ftdm_status_t zt_channel_process_event(ftdm_channel_t *fchan,
*event_id = FTDM_OOB_NOOP; /* What else could we do? */
}
break;
case ZT_EVENT_POLARITY:
{
ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Got polarity reverse (ZT_EVENT_POLARITY)\n");
*event_id = FTDM_OOB_POLARITY_REVERSE;
}
break;
case ZT_EVENT_NONE:
{
ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "No event\n");
@@ -29,6 +29,12 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
*
* Moises Silva <moy@sangoma.com>
* W McRoberts <fs@whmcr.com>
*
*/
#ifndef FTDM_ZT_H
@@ -349,6 +355,7 @@ ZT_ABIT = 8
#define DAHDI_SETTXBITS _IOW (DAHDI_CODE, 43, int)
#define DAHDI_GETRXBITS _IOR (DAHDI_CODE, 43, int)
#define DAHDI_SETPOLARITY _IOW (DAHDI_CODE, 92, int) /* Polarity setting for FXO lines */
#endif
+3 -3
View File
@@ -926,20 +926,20 @@ typedef enum {
/*! \brief IO statistics */
typedef struct {
struct {
uint64_t packets;
uint32_t errors;
uint16_t flags;
uint8_t queue_size; /*!< max queue size configured */
uint8_t queue_len; /*!< Current number of elements in queue */
uint64_t packets;
} rx;
struct {
uint64_t idle_packets;
uint64_t packets;
uint32_t errors;
uint16_t flags;
uint8_t idle_packets;
uint8_t queue_size; /*!< max queue size configured */
uint8_t queue_len; /*!< Current number of elements in queue */
uint64_t packets;
} tx;
} ftdm_channel_iostats_t;
@@ -4,10 +4,10 @@
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mftilla Public License Version
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mftilla.org/MPL/
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
@@ -33,8 +33,8 @@
* Exception:
* The author hereby grants the use of this source code under the
* following license if and only if the source code is distributed
* as part of the freetdm library. Any use or distribution of this
* source code outside the scope of the freetdm library will nullify the
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
* following license and reinact the MPL 1.1 as stated above.
*
* Copyright (c) 2007, Anthony Minessale II
@@ -2,13 +2,60 @@
* libteletone
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is tone_detect.c - General telephony tone detection, and specific detection of DTMF.
*
*
* The Initial Developer of the Original Code is
* Stephen Underwood <steveu@coppice.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* The the original interface designed by Steve Underwood was preserved to retain
*the optimizations when considering DTMF tones though the names were changed in the interest
* of namespace.
*
* Much less efficient expansion interface was added to allow for the detection of
* a single arbitrary tone combination which may also exceed 2 simultaneous tones.
* (controlled by compile time constant TELETONE_MAX_TONES)
*
* Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org>
*
*
* libteletone_detect.c Tone Detection Code
*
*
*********************************************************************************
*
* Derived from tone_detect.h - General telephony tone detection, and specific
* detection of DTMF.
*
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
*
* Despite my general liking of the GPL, I place this code in the
* public domain for the benefit of all mankind - even the slimy
* ones who might try to proprietize my work and use it to my
* detriment.
*
*
* Exception:
* The author hereby grants the use of this source code under the
* following license if and only if the source code is distributed
* as part of the freetdm library. Any use or distribution of this
* source code outside the scope of the freetdm library will nullify the
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
* following license and reinact the MPL 1.1 as stated above.
*
* Copyright (c) 2007, Anthony Minessale II
@@ -41,20 +88,6 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*********************************************************************************
*
* Derived from tone_detect.h - General telephony tone detection, and specific
* detection of DTMF.
*
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
*
* Despite my general liking of the GPL, I place this code in the
* public domain for the benefit of all mankind - even the slimy
* ones who might try to proprietize my work and use it to my
* detriment.
*
*
*/
#ifndef LIBTELETONE_DETECT_H
@@ -101,6 +134,14 @@ extern "C" {
#define BLOCK_LEN 102
#define M_TWO_PI 2.0*M_PI
typedef enum {
TT_HIT_NONE = 0,
TT_HIT_BEGIN = 1,
TT_HIT_MIDDLE = 2,
TT_HIT_END = 3
} teletone_hit_type_t;
/*! \brief A continer for the elements of a Goertzel Algorithm (The names are from his formula) */
typedef struct {
float v2;
@@ -114,16 +155,19 @@ extern "C" {
int hit2;
int hit3;
int hit4;
int mhit;
int dur;
int zc;
teletone_goertzel_state_t row_out[GRID_FACTOR];
teletone_goertzel_state_t col_out[GRID_FACTOR];
teletone_goertzel_state_t row_out2nd[GRID_FACTOR];
teletone_goertzel_state_t col_out2nd[GRID_FACTOR];
float energy;
float lenergy;
int current_sample;
char digits[TELETONE_MAX_DTMF_DIGITS + 1];
char digit;
int current_digits;
int detected_digits;
int lost_digits;
@@ -196,7 +240,7 @@ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf
\param samples the number of samples present in sample_buffer
\return true when DTMF was detected or false when it is not
*/
TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
int16_t sample_buffer[],
int samples);
/*!
@@ -206,9 +250,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
\param max the maximum length of buf
\return the number of characters written to buf
*/
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state,
char *buf,
int max);
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur);
/*!
\brief Step through the Goertzel Algorithm for each sample in a buffer
@@ -2,6 +2,41 @@
* libteletone
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is libteletone
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
*
*
* libteletone.h -- Tone Generator
*
*
*
* Exception:
* The author hereby grants the use of this source code under the
* following license if and only if the source code is distributed
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
* following license and reinact the MPL 1.1 as stated above.
*
* Copyright (c) 2007, Anthony Minessale II
* All rights reserved.
*
+110 -52
View File
@@ -2,14 +2,62 @@
* libteletone
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is tone_detect.c - General telephony tone detection, and specific detection of DTMF.
*
*
* The Initial Developer of the Original Code is
* Stephen Underwood <steveu@coppice.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* The the original interface designed by Steve Underwood was preserved to retain
*the optimizations when considering DTMF tones though the names were changed in the interest
* of namespace.
*
* Much less efficient expansion interface was added to allow for the detection of
* a single arbitrary tone combination which may also exceed 2 simultaneous tones.
* (controlled by compile time constant TELETONE_MAX_TONES)
*
* Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org>
*
*
* libteletone_detect.c Tone Detection Code
*
*
*********************************************************************************
*
* Derived from tone_detect.c - General telephony tone detection, and specific
* detection of DTMF.
*
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
*
* Despite my general liking of the GPL, I place this code in the
* public domain for the benefit of all mankind - even the slimy
* ones who might try to proprietize my work and use it to my
* detriment.
*
*
* Exception:
* The author hereby grants the use of this source code under the
* following license if and only if the source code is distributed
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
* following license and reinact the MPL 1.1 as stated above.
*
* Copyright (c) 2007, Anthony Minessale II
* All rights reserved.
*
@@ -40,21 +88,6 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*********************************************************************************
*
* Derived from tone_detect.c - General telephony tone detection, and specific
* detection of DTMF.
*
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
*
* Despite my general liking of the GPL, I place this code in the
* public domain for the benefit of all mankind - even the slimy
* ones who might try to proprietize my work and use it to my
* detriment.
*
*
*
*/
#include <libteletone_detect.h>
@@ -67,7 +100,8 @@
#include <time.h>
#include <fcntl.h>
#define LOW_ENG 10000000
#define ZC 2
static teletone_detection_descriptor_t dtmf_detect_row[GRID_FACTOR];
static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR];
static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR];
@@ -132,8 +166,8 @@ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf
dtmf_detect_state->current_sample = 0;
dtmf_detect_state->detected_digits = 0;
dtmf_detect_state->lost_digits = 0;
dtmf_detect_state->digits[0] = '\0';
dtmf_detect_state->mhit = 0;
dtmf_detect_state->digit = 0;
dtmf_detect_state->dur = 0;
}
TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map)
@@ -266,7 +300,7 @@ TELETONE_API(int) teletone_multi_tone_detect (teletone_multi_tone_t *mt,
}
TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
int16_t sample_buffer[],
int samples)
{
@@ -281,6 +315,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
int best_col;
char hit;
int limit;
teletone_hit_type_t r = 0;
hit = 0;
for (sample = 0; sample < samples; sample = limit) {
@@ -317,6 +352,32 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
}
if (dtmf_detect_state->zc > 0) {
if (dtmf_detect_state->energy < LOW_ENG && dtmf_detect_state->lenergy < LOW_ENG) {
if (!--dtmf_detect_state->zc) {
/* Reinitialise the detector for the next block */
dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0;
for (i = 0; i < GRID_FACTOR; i++) {
goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
}
dtmf_detect_state->dur -= samples;
return TT_HIT_END;
}
}
dtmf_detect_state->dur += samples;
dtmf_detect_state->lenergy = dtmf_detect_state->energy;
dtmf_detect_state->energy = 0.0;
dtmf_detect_state->current_sample = 0;
return TT_HIT_MIDDLE;
} else if (dtmf_detect_state->digit) {
return TT_HIT_END;
}
dtmf_detect_state->current_sample += (limit - sample);
if (dtmf_detect_state->current_sample < BLOCK_LEN) {
continue;
@@ -361,58 +422,55 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
back to back differing digits. More importantly, it
can work with nasty phones that give a very wobbly start
to a digit. */
if (hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
dtmf_detect_state->mhit = hit;
if (! r && hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++;
dtmf_detect_state->detected_digits++;
if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) {
dtmf_detect_state->digits[dtmf_detect_state->current_digits++] = hit;
dtmf_detect_state->digits[dtmf_detect_state->current_digits] = '\0';
dtmf_detect_state->digit = hit;
} else {
dtmf_detect_state->lost_digits++;
}
else
{
dtmf_detect_state->lost_digits++;
}
if (!dtmf_detect_state->zc) {
dtmf_detect_state->zc = ZC;
dtmf_detect_state->dur = 0;
r = TT_HIT_BEGIN;
break;
}
}
}
}
dtmf_detect_state->hit1 = dtmf_detect_state->hit2;
dtmf_detect_state->hit2 = dtmf_detect_state->hit3;
dtmf_detect_state->hit3 = hit;
/* Reinitialise the detector for the next block */
for (i = 0; i < GRID_FACTOR; i++) {
goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
}
dtmf_detect_state->energy = 0.0;
dtmf_detect_state->current_sample = 0;
}
if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) {
dtmf_detect_state->mhit = 0;
return(0);
}
return (hit);
return r;
}
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state,
char *buf,
int max)
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur)
{
teletone_assert(dtmf_detect_state->current_digits <= TELETONE_MAX_DTMF_DIGITS);
if (!dtmf_detect_state->digit) {
return 0;
}
if (max > dtmf_detect_state->current_digits) {
max = dtmf_detect_state->current_digits;
*buf = dtmf_detect_state->digit;
*dur = dtmf_detect_state->dur;
if (!dtmf_detect_state->zc) {
dtmf_detect_state->dur = 0;
dtmf_detect_state->digit = 0;
}
if (max > 0) {
memcpy (buf, dtmf_detect_state->digits, max);
memmove (dtmf_detect_state->digits, dtmf_detect_state->digits + max, dtmf_detect_state->current_digits - max);
dtmf_detect_state->current_digits -= max;
}
buf[max] = '\0';
return max;
return 1;
}
/* For Emacs:
+57 -6
View File
@@ -1,5 +1,41 @@
/*
* libteletone_generate.c -- Tone Generator
* libteletone
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is libteletone
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
*
*
* libteletone.c -- Tone Generator
*
*
*
* Exception:
* The author hereby grants the use of this source code under the
* following license if and only if the source code is distributed
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
* following license and reinact the MPL 1.1 as stated above.
*
* Copyright (c) 2007, Anthony Minessale II
* All rights reserved.
@@ -34,7 +70,6 @@
*/
#include <libteletone.h>
#include "private/ftdm_core.h"
#define SMAX 32767
#define SMIN -32768
@@ -111,7 +146,7 @@ TELETONE_API(int) teletone_init_session(teletone_generation_session_t *ts, int b
ts->decay_step = 0;
ts->decay_factor = 1;
if (buflen) {
if ((ts->buffer = ftdm_calloc(buflen, sizeof(teletone_audio_t))) == 0) {
if ((ts->buffer = calloc(buflen, sizeof(teletone_audio_t))) == 0) {
return -1;
}
ts->datalen = buflen;
@@ -142,7 +177,7 @@ TELETONE_API(int) teletone_init_session(teletone_generation_session_t *ts, int b
TELETONE_API(int) teletone_destroy_session(teletone_generation_session_t *ts)
{
if (ts->buffer) {
ftdm_safe_free(ts->buffer);
free(ts->buffer);
ts->buffer = NULL;
ts->samples = 0;
}
@@ -270,6 +305,19 @@ TELETONE_API(int) teletone_mux_tones(teletone_generation_session_t *ts, teletone
return ts->samples / ts->channels;
}
/* don't ask */
static char *my_strdup (const char *s)
{
size_t len = strlen (s) + 1;
void *new = malloc (len);
if (new == NULL) {
return NULL;
}
return (char *) memcpy (new, s, len);
}
TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cmd)
{
char *data = NULL, *cur = NULL, *end = NULL;
@@ -280,7 +328,7 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm
}
do {
if (!(data = ftdm_strdup(cmd))) {
if (!(data = my_strdup(cmd))) {
return -1;
}
@@ -363,6 +411,9 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm
*e++ = '\0';
}
do {
if (!p) {
break;
}
if ((next = strchr(p, ',')) != 0) {
*next++ = '\0';
}
@@ -427,7 +478,7 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm
}
}
bottom:
ftdm_safe_free(data);
free(data);
data = NULL;
if (ts->LOOPS > 0) {
ts->LOOPS--;