a few twiax to prevent a race condition

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3991 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2007-01-19 01:26:22 +00:00
parent 41541428fc
commit b25743c4d1
1 changed files with 94 additions and 89 deletions

View File

@ -98,6 +98,9 @@ struct private_object {
//switch_thread_cond_t *cond; //switch_thread_cond_t *cond;
}; };
typedef struct private_object private_t;
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan) SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan)
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, globals.codec_string) SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, globals.codec_string)
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_rates_string, globals.codec_rates_string) SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_rates_string, globals.codec_rates_string)
@ -210,7 +213,7 @@ typedef enum {
IAX_QUERY = 2 IAX_QUERY = 2
} iax_io_t; } iax_io_t;
static switch_status_t iax_set_codec(struct private_object *tech_pvt, struct iax_session *iax_session, static switch_status_t iax_set_codec(private_t *tech_pvt, struct iax_session *iax_session,
unsigned int *format, unsigned int *cababilities, unsigned short *samprate, unsigned int *format, unsigned int *cababilities, unsigned short *samprate,
iax_io_t io) iax_io_t io)
{ {
@ -444,6 +447,15 @@ static void iax_out_cb(const char *s)
} }
} }
static void tech_init(private_t *tech_pvt, switch_core_session_t *session)
{
tech_pvt->read_frame.data = tech_pvt->databuf;
tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
switch_core_session_set_private(session, tech_pvt);
tech_pvt->session = session;
}
/* /*
State methods they get called when the state changes to the specific state State methods they get called when the state changes to the specific state
@ -453,7 +465,7 @@ so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip i
static switch_status_t channel_on_init(switch_core_session_t *session) static switch_status_t channel_on_init(switch_core_session_t *session)
{ {
switch_channel_t *channel; switch_channel_t *channel;
struct private_object *tech_pvt = NULL; private_t *tech_pvt = NULL;
tech_pvt = switch_core_session_get_private(session); tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL); assert(tech_pvt != NULL);
@ -461,13 +473,12 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
assert(channel != NULL); assert(channel != NULL);
tech_pvt->read_frame.data = tech_pvt->databuf;
tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
iax_set_private(tech_pvt->iax_session, tech_pvt); iax_set_private(tech_pvt->iax_session, tech_pvt);
switch_set_flag_locked(tech_pvt, TFLAG_IO); switch_set_flag_locked(tech_pvt, TFLAG_IO);
switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
//switch_thread_cond_create(&tech_pvt->cond, switch_core_session_get_pool(session)); //switch_thread_cond_create(&tech_pvt->cond, switch_core_session_get_pool(session));
//switch_mutex_lock(tech_pvt->mutex); //switch_mutex_lock(tech_pvt->mutex);
@ -483,7 +494,7 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
static switch_status_t channel_on_ring(switch_core_session_t *session) static switch_status_t channel_on_ring(switch_core_session_t *session)
{ {
switch_channel_t *channel = NULL; switch_channel_t *channel = NULL;
struct private_object *tech_pvt = NULL; private_t *tech_pvt = NULL;
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
assert(channel != NULL); assert(channel != NULL);
@ -500,7 +511,7 @@ static switch_status_t channel_on_execute(switch_core_session_t *session)
{ {
switch_channel_t *channel = NULL; switch_channel_t *channel = NULL;
struct private_object *tech_pvt = NULL; private_t *tech_pvt = NULL;
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
assert(channel != NULL); assert(channel != NULL);
@ -517,7 +528,7 @@ static switch_status_t channel_on_execute(switch_core_session_t *session)
static switch_status_t channel_on_hangup(switch_core_session_t *session) static switch_status_t channel_on_hangup(switch_core_session_t *session)
{ {
switch_channel_t *channel = NULL; switch_channel_t *channel = NULL;
struct private_object *tech_pvt = NULL; private_t *tech_pvt = NULL;
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
assert(channel != NULL); assert(channel != NULL);
@ -559,7 +570,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig) static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig)
{ {
switch_channel_t *channel = NULL; switch_channel_t *channel = NULL;
struct private_object *tech_pvt = NULL; private_t *tech_pvt = NULL;
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
assert(channel != NULL); assert(channel != NULL);
@ -600,7 +611,7 @@ static switch_status_t channel_on_transmit(switch_core_session_t *session)
static switch_status_t channel_waitfor_read(switch_core_session_t *session, int ms, int stream_id) static switch_status_t channel_waitfor_read(switch_core_session_t *session, int ms, int stream_id)
{ {
struct private_object *tech_pvt = NULL; private_t *tech_pvt = NULL;
tech_pvt = switch_core_session_get_private(session); tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL); assert(tech_pvt != NULL);
@ -610,7 +621,7 @@ static switch_status_t channel_waitfor_read(switch_core_session_t *session, int
static switch_status_t channel_waitfor_write(switch_core_session_t *session, int ms, int stream_id) static switch_status_t channel_waitfor_write(switch_core_session_t *session, int ms, int stream_id)
{ {
struct private_object *tech_pvt = NULL; private_t *tech_pvt = NULL;
tech_pvt = switch_core_session_get_private(session); tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL); assert(tech_pvt != NULL);
@ -621,7 +632,7 @@ static switch_status_t channel_waitfor_write(switch_core_session_t *session, int
static switch_status_t channel_send_dtmf(switch_core_session_t *session, char *dtmf) static switch_status_t channel_send_dtmf(switch_core_session_t *session, char *dtmf)
{ {
struct private_object *tech_pvt = NULL; private_t *tech_pvt = NULL;
char *digit; char *digit;
tech_pvt = switch_core_session_get_private(session); tech_pvt = switch_core_session_get_private(session);
@ -639,7 +650,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
switch_io_flag_t flags, int stream_id) switch_io_flag_t flags, int stream_id)
{ {
switch_channel_t *channel = NULL; switch_channel_t *channel = NULL;
struct private_object *tech_pvt = NULL; private_t *tech_pvt = NULL;
switch_time_t started = switch_time_now(); switch_time_t started = switch_time_now();
unsigned int elapsed; unsigned int elapsed;
@ -649,16 +660,18 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
tech_pvt = switch_core_session_get_private(session); tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL); assert(tech_pvt != NULL);
tech_pvt->read_frame.flags = SFF_NONE; tech_pvt->read_frame.flags = SFF_NONE;
*frame = NULL;
while (switch_test_flag(tech_pvt, TFLAG_IO)) { while (switch_test_flag(tech_pvt, TFLAG_IO)) {
if (!switch_test_flag(tech_pvt, TFLAG_CODEC)) {
switch_yield(1000);
continue;
}
//switch_thread_cond_wait(tech_pvt->cond, tech_pvt->mutex); //switch_thread_cond_wait(tech_pvt->cond, tech_pvt->mutex);
if (switch_test_flag(tech_pvt, TFLAG_BREAK)) { if (switch_test_flag(tech_pvt, TFLAG_BREAK)) {
switch_clear_flag(tech_pvt, TFLAG_BREAK); switch_clear_flag(tech_pvt, TFLAG_BREAK);
tech_pvt->read_frame.datalen = 13; goto cng;
memset(tech_pvt->read_frame.data, 0, 13);
tech_pvt->read_frame.flags = SFF_CNG;
*frame = &tech_pvt->read_frame;
return SWITCH_STATUS_SUCCESS;
} }
if (!switch_test_flag(tech_pvt, TFLAG_IO)) { if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
@ -692,13 +705,21 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
cng:
tech_pvt->read_frame.datalen = 13;
memset(tech_pvt->read_frame.data, 0, 13);
tech_pvt->read_frame.flags = SFF_CNG;
*frame = &tech_pvt->read_frame;
return SWITCH_STATUS_SUCCESS;
} }
static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, int timeout, static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, int timeout,
switch_io_flag_t flags, int stream_id) switch_io_flag_t flags, int stream_id)
{ {
switch_channel_t *channel = NULL; switch_channel_t *channel = NULL;
struct private_object *tech_pvt = NULL; private_t *tech_pvt = NULL;
//switch_frame_t *pframe; //switch_frame_t *pframe;
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
@ -725,7 +746,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
static switch_status_t channel_answer_channel(switch_core_session_t *session) static switch_status_t channel_answer_channel(switch_core_session_t *session)
{ {
struct private_object *tech_pvt; private_t *tech_pvt;
switch_channel_t *channel = NULL; switch_channel_t *channel = NULL;
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
@ -785,20 +806,16 @@ static switch_status_t channel_outgoing_channel(switch_core_session_t *session,
switch_core_session_t **new_session, switch_memory_pool_t *pool) switch_core_session_t **new_session, switch_memory_pool_t *pool)
{ {
if ((*new_session = switch_core_session_request(&channel_endpoint_interface, pool)) != 0) { if ((*new_session = switch_core_session_request(&channel_endpoint_interface, pool)) != 0) {
struct private_object *tech_pvt; private_t *tech_pvt;
switch_channel_t *channel; switch_channel_t *channel;
switch_caller_profile_t *caller_profile; switch_caller_profile_t *caller_profile;
unsigned int req = 0, cap = 0; unsigned int req = 0, cap = 0;
unsigned short samprate = 0; unsigned short samprate = 0;
switch_core_session_add_stream(*new_session, NULL); switch_core_session_add_stream(*new_session, NULL);
if ((tech_pvt = if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) {
(struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object))) != 0) {
memset(tech_pvt, 0, sizeof(*tech_pvt));
switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(*new_session));
channel = switch_core_session_get_channel(*new_session); channel = switch_core_session_get_channel(*new_session);
switch_core_session_set_private(*new_session, tech_pvt); tech_init(tech_pvt, *new_session);
tech_pvt->session = *new_session;
} else { } else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
switch_core_session_destroy(new_session); switch_core_session_destroy(new_session);
@ -929,6 +946,19 @@ static switch_status_t load_config(void)
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status_t tech_media(private_t *tech_pvt, struct iax_event *iaxevent)
{
unsigned int cap = iax_session_get_capability(iaxevent->session);
unsigned int format = iaxevent->ies.format;
switch_status_t status = SWITCH_STATUS_SUCCESS;
if (!switch_test_flag(tech_pvt, TFLAG_CODEC) &&
(status = iax_set_codec(tech_pvt, iaxevent->session, &format, &cap, &iaxevent->ies.samprate, IAX_SET)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec Error %u %u\n", iaxevent->ies.format, iaxevent->ies.capability);
}
return status;
}
SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void) SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void)
{ {
@ -960,8 +990,6 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void)
} }
for (;;) { for (;;) {
if (running == -1) { if (running == -1) {
break; break;
} }
@ -981,8 +1009,13 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void)
switch_yield(waitlen); switch_yield(waitlen);
continue; continue;
} else { } else {
struct private_object *tech_pvt = iax_get_private(iaxevent->session); private_t *tech_pvt = NULL;
switch_channel_t *channel = NULL;
if ((tech_pvt = iax_get_private(iaxevent->session))) {
channel = switch_core_session_get_channel(tech_pvt->session);
}
if (globals.debug && iaxevent->etype != IAX_EVENT_VOICE) { if (globals.debug && iaxevent->etype != IAX_EVENT_VOICE) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Event %d [%s]!\n", switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Event %d [%s]!\n",
iaxevent->etype, IAXNAMES[iaxevent->etype]); iaxevent->etype, IAXNAMES[iaxevent->etype]);
@ -1001,17 +1034,8 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void)
break; break;
case IAX_EVENT_ACCEPT: case IAX_EVENT_ACCEPT:
if (tech_pvt) { if (tech_pvt) {
unsigned int cap = iax_session_get_capability(iaxevent->session); tech_media(tech_pvt, iaxevent);
unsigned int format = iaxevent->ies.format;
if (iax_set_codec(tech_pvt, iaxevent->session, &format, &cap, &iaxevent->ies.samprate, IAX_SET) !=
SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "WTF? %u %u\n", iaxevent->ies.format,
iaxevent->ies.capability);
}
} }
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Call accepted.\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Call accepted.\n");
break; break;
case IAX_EVENT_RINGA: case IAX_EVENT_RINGA:
@ -1022,20 +1046,18 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void)
break; break;
case IAX_EVENT_ANSWER: case IAX_EVENT_ANSWER:
// the other side answered our call // the other side answered our call
if (tech_pvt) { if (channel) {
switch_channel_t *channel; tech_media(tech_pvt, iaxevent);
if ((channel = switch_core_session_get_channel(tech_pvt->session)) != 0) {
if (switch_channel_test_flag(channel, CF_ANSWERED)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "WTF Mutiple Answer %s?\n",
switch_channel_get_name(channel));
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Answer %s\n",
switch_channel_get_name(channel));
switch_channel_answer(channel);
}
}
}
if (switch_channel_test_flag(channel, CF_ANSWERED)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "WTF Mutiple Answer %s?\n", switch_channel_get_name(channel));
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Answer %s\n", switch_channel_get_name(channel));
switch_channel_mark_answered(channel);
}
}
break; break;
case IAX_EVENT_CONNECT: case IAX_EVENT_CONNECT:
// incoming call detected // incoming call detected
@ -1051,18 +1073,13 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "New Inbound Channel %s!\n", switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "New Inbound Channel %s!\n",
iaxevent->ies.calling_name); iaxevent->ies.calling_name);
if ((session = switch_core_session_request(&channel_endpoint_interface, NULL)) != 0) { if ((session = switch_core_session_request(&channel_endpoint_interface, NULL)) != 0) {
struct private_object *tech_pvt; private_t *tech_pvt;
switch_channel_t *channel; switch_channel_t *channel;
switch_core_session_add_stream(session, NULL); switch_core_session_add_stream(session, NULL);
if ((tech_pvt = if ((tech_pvt = (private_t *) switch_core_session_alloc(session, sizeof(private_t))) != 0) {
(struct private_object *) switch_core_session_alloc(session,
sizeof(struct private_object))) != 0) {
memset(tech_pvt, 0, sizeof(*tech_pvt));
switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
switch_core_session_set_private(session, tech_pvt); tech_init(tech_pvt, session);
tech_pvt->session = session;
} else { } else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
switch_core_session_destroy(&session); switch_core_session_destroy(&session);
@ -1111,24 +1128,18 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Rejected call.\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Rejected call.\n");
case IAX_EVENT_BUSY: case IAX_EVENT_BUSY:
case IAX_EVENT_HANGUP: case IAX_EVENT_HANGUP:
if (tech_pvt) { if (channel) {
switch_channel_t *channel;
switch_mutex_lock(tech_pvt->flag_mutex); switch_mutex_lock(tech_pvt->flag_mutex);
switch_clear_flag(tech_pvt, TFLAG_IO); switch_clear_flag(tech_pvt, TFLAG_IO);
switch_clear_flag(tech_pvt, TFLAG_VOICE); switch_clear_flag(tech_pvt, TFLAG_VOICE);
switch_mutex_unlock(tech_pvt->flag_mutex); switch_mutex_unlock(tech_pvt->flag_mutex);
if ((channel = switch_core_session_get_channel(tech_pvt->session)) != 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hangup %s\n", switch_channel_get_name(channel)); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hangup %s\n", switch_channel_get_name(channel));
switch_set_flag_locked(tech_pvt, TFLAG_HANGUP); switch_set_flag_locked(tech_pvt, TFLAG_HANGUP);
switch_channel_hangup(channel, iaxevent->etype == IAX_EVENT_HANGUP ? SWITCH_CAUSE_NORMAL_CLEARING : SWITCH_CAUSE_FACILITY_REJECTED); switch_channel_hangup(channel, iaxevent->etype == IAX_EVENT_HANGUP ? SWITCH_CAUSE_NORMAL_CLEARING : SWITCH_CAUSE_FACILITY_REJECTED);
//switch_thread_cond_signal(tech_pvt->cond); //switch_thread_cond_signal(tech_pvt->cond);
iaxevent->session = NULL; iaxevent->session = NULL;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No Session? %s\n",
switch_test_flag(tech_pvt, TFLAG_VOICE) ? "yes" : "no");
}
} }
break; break;
case IAX_EVENT_CNG: case IAX_EVENT_CNG:
@ -1137,9 +1148,7 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void)
break; break;
case IAX_EVENT_VOICE: case IAX_EVENT_VOICE:
if (tech_pvt && (tech_pvt->read_frame.datalen = iaxevent->datalen) != 0) { if (tech_pvt && (tech_pvt->read_frame.datalen = iaxevent->datalen) != 0) {
switch_channel_t *channel; if (channel && switch_channel_get_state(channel) <= CS_HANGUP) {
if (((channel = switch_core_session_get_channel(tech_pvt->session)) != 0)
&& switch_channel_get_state(channel) <= CS_HANGUP) {
int bytes, frames; int bytes, frames;
if (!switch_test_flag(tech_pvt, TFLAG_CODEC)) { if (!switch_test_flag(tech_pvt, TFLAG_CODEC)) {
@ -1154,7 +1163,6 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void)
frames = 1; frames = 1;
} }
tech_pvt->read_frame.samples = frames * tech_pvt->read_codec.implementation->samples_per_frame; tech_pvt->read_frame.samples = frames * tech_pvt->read_codec.implementation->samples_per_frame;
memcpy(tech_pvt->read_frame.data, iaxevent->data, iaxevent->datalen); memcpy(tech_pvt->read_frame.data, iaxevent->data, iaxevent->datalen);
/* wake up the i/o thread */ /* wake up the i/o thread */
@ -1168,16 +1176,13 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void)
//session[0] = iaxevent->session; //session[0] = iaxevent->session;
break; break;
case IAX_EVENT_DTMF: case IAX_EVENT_DTMF:
if (tech_pvt) { if (channel) {
switch_channel_t *channel; char str[2] = { (char)iaxevent->subclass };
if ((channel = switch_core_session_get_channel(tech_pvt->session)) != 0) { if (globals.debug) {
char str[2] = { (char)iaxevent->subclass }; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s DTMF %s\n", str,
if (globals.debug) { switch_channel_get_name(channel));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s DTMF %s\n", str, }
switch_channel_get_name(channel)); switch_channel_queue_dtmf(channel, str);
}
switch_channel_queue_dtmf(channel, str);
}
} }
break; break;