From 757e9e20bdac33e6e368254c125d6fd12a9cbc75 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Mon, 4 Oct 2010 16:58:29 -0400 Subject: [PATCH 1/7] fix conference deadlock on probobly inpossible buffer failure --- src/mod/applications/mod_conference/mod_conference.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 7018294546..b9364ff24a 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -1330,6 +1330,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v switch_mutex_unlock(omember->audio_out_mutex); if (!ok) { + switch_mutex_unlock(conference->mutex); goto end; } } From dc0f761b1492a0911f66b664a2a7ede5ad548638 Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Mon, 4 Oct 2010 14:01:36 -0700 Subject: [PATCH 2/7] Phrase file updates (en) --- docs/phrase/phrase_en.xml | 43 +++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/docs/phrase/phrase_en.xml b/docs/phrase/phrase_en.xml index d519350d35..6d582e77a1 100644 --- a/docs/phrase/phrase_en.xml +++ b/docs/phrase/phrase_en.xml @@ -364,6 +364,21 @@ + + + + + + + + + + + + + + + @@ -387,17 +402,37 @@ - + - + - + + - + + + + + + + + + + + + + + + + + + + + From 0ca8d88ed49aaa03d32997ba7a2c5cfdac934b55 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Mon, 4 Oct 2010 17:43:10 -0500 Subject: [PATCH 3/7] declinatio mortuus obfirmo --- .../mod_conference/mod_conference.c | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index b9364ff24a..e1570a7af5 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -1914,6 +1914,8 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v uint32_t hangover = 40, hangunder = 15, hangover_hits = 0, hangunder_hits = 0, energy_level = 0, diff_level = 400; switch_codec_implementation_t read_impl = { 0 }; switch_core_session_t *session = member->session; + int check_floor_change; + switch_assert(member != NULL); switch_clear_flag_locked(member, MFLAG_TALKING); @@ -1926,6 +1928,7 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v and mux it with any audio from other channels. */ while (switch_test_flag(member, MFLAG_RUNNING) && switch_channel_ready(channel)) { + check_floor_change = 0; if (switch_channel_ready(channel) && switch_channel_test_app_flag(channel, CF_APP_TAGGED)) { switch_yield(100000); @@ -2083,25 +2086,7 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v } if (diff >= diff_level || ++hangunder_hits >= hangunder) { - - switch_mutex_lock(member->conference->member_mutex); - if ((!member->conference->floor_holder || - !switch_test_flag(member->conference->floor_holder, MFLAG_TALKING) || - ((member->score_iir > SCORE_IIR_SPEAKING_MAX) && (member->conference->floor_holder->score_iir < SCORE_IIR_SPEAKING_MIN))) && - (!switch_test_flag(member->conference, CFLAG_VID_FLOOR) || switch_channel_test_flag(channel, CF_VIDEO))) { - - if (test_eflag(member->conference, EFLAG_FLOOR_CHANGE) && - switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { - conference_add_event_member_data(member, event); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "floor-change"); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Old-ID", "%d", - member->conference->floor_holder ? member->conference->floor_holder->id : 0); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-ID", "%d", member->conference->floor_holder ? member->id : 0); - switch_event_fire(&event); - } - member->conference->floor_holder = member; - } - switch_mutex_unlock(member->conference->member_mutex); + check_floor_change = 1; hangover_hits = hangunder_hits = 0; member->last_talking = switch_epoch_time_now(NULL); @@ -2191,6 +2176,28 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v do_continue: switch_mutex_unlock(member->read_mutex); + + if (check_floor_change) { + switch_mutex_lock(member->conference->member_mutex); + if ((!member->conference->floor_holder || + !switch_test_flag(member->conference->floor_holder, MFLAG_TALKING) || + ((member->score_iir > SCORE_IIR_SPEAKING_MAX) && (member->conference->floor_holder->score_iir < SCORE_IIR_SPEAKING_MIN))) && + (!switch_test_flag(member->conference, CFLAG_VID_FLOOR) || switch_channel_test_flag(channel, CF_VIDEO))) { + + if (test_eflag(member->conference, EFLAG_FLOOR_CHANGE) && + switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { + conference_add_event_member_data(member, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "floor-change"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Old-ID", "%d", + member->conference->floor_holder ? member->conference->floor_holder->id : 0); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-ID", "%d", member->conference->floor_holder ? member->id : 0); + switch_event_fire(&event); + } + member->conference->floor_holder = member; + } + switch_mutex_unlock(member->conference->member_mutex); + } + } From 094d8f9599c2b5fa365dc175b360288c2b588bae Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 4 Oct 2010 17:55:04 -0500 Subject: [PATCH 4/7] fix dialog-info presence issue --- src/mod/endpoints/mod_sofia/sofia_presence.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index d9b3de0a8b..3a01e1e003 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -571,22 +571,22 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) switch_safe_free(sql); - sql = switch_mprintf("select sip_registrations.sip_user, sip_registrations.orig_server_host, sip_registrations.status, " + sql = switch_mprintf("select sip_registrations.sip_user, sip_registrations.orig_hostname, sip_registrations.status, " "sip_registrations.rpid,'', sip_dialogs.uuid, sip_dialogs.state, sip_dialogs.direction, " "sip_dialogs.sip_to_user, sip_dialogs.sip_to_host, sip_presence.status,sip_presence.rpid,sip_presence.open_closed," "'%q','%q' " "from sip_registrations left join sip_dialogs on " "(sip_dialogs.sip_from_user = sip_registrations.sip_user " - "and (sip_dialogs.sip_from_host = sip_registrations.orig_server_host or " + "and (sip_dialogs.sip_from_host = sip_registrations.orig_hostname or " "sip_dialogs.sip_from_host = sip_registrations.sip_host) ) " "left join sip_presence on " - "(sip_registrations.sip_user=sip_presence.sip_user and sip_registrations.orig_server_host=sip_presence.sip_host and " + "(sip_registrations.sip_user=sip_presence.sip_user and sip_registrations.orig_hostname=sip_presence.sip_host and " "sip_registrations.profile_name=sip_presence.profile_name) " "where sip_registrations.sip_user='%q' and " - "(sip_registrations.orig_server_host='%q' or sip_registrations.sip_host='%q' " + "(sip_registrations.orig_hostname='%q' or sip_registrations.sip_host='%q' " "or sip_registrations.presence_hosts like '%%%q%%')", dh.status, dh.rpid, probe_euser, probe_host, probe_host, probe_host); switch_assert(sql); From 7f3319dc1160c6533081a853a682480dc8fed02d Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 4 Oct 2010 18:23:43 -0500 Subject: [PATCH 5/7] add switch_ivr_dmachine async digit parser to core --- src/include/switch_ivr.h | 22 ++ src/include/switch_types.h | 16 ++ src/mod/applications/mod_fifo/mod_fifo.c | 8 +- src/switch_ivr.c | 18 +- src/switch_ivr_async.c | 277 ++++++++++++++++++++++- src/switch_ivr_play_say.c | 91 ++++++-- 6 files changed, 406 insertions(+), 26 deletions(-) diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index 4c562a51d7..5fee7baefa 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -842,6 +842,28 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sound_test(switch_core_session_t *ses SWITCH_DECLARE(void) switch_process_import(switch_core_session_t *session, switch_channel_t *peer_channel, const char *varname); SWITCH_DECLARE(switch_bool_t) switch_ivr_uuid_exists(const char *uuid); + + +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_create(switch_ivr_dmachine_t **dmachine_p, + switch_memory_pool_t *pool, + uint32_t digit_timeout, uint32_t input_timeout); + +SWITCH_DECLARE(void) switch_ivr_dmachine_destroy(switch_ivr_dmachine_t **dmachine); + +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_bind(switch_ivr_dmachine_t *dmachine, + const char *digits, + int32_t key, + switch_ivr_dmachine_callback_t callback, + void *user_data); + +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_feed(switch_ivr_dmachine_t *dmachine, const char *digits, switch_ivr_dmachine_match_t **match); +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_clear(switch_ivr_dmachine_t *dmachine); +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_match_t **match_p); +SWITCH_DECLARE(switch_ivr_dmachine_match_t *) switch_ivr_dmachine_get_match(switch_ivr_dmachine_t *dmachine); + + + + /** @} */ SWITCH_END_EXTERN_C diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 668fdc81c4..32fb141d42 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -833,6 +833,7 @@ typedef enum { SWITCH_STATUS_NOUNLOAD, SWITCH_STATUS_IGNORE, SWITCH_STATUS_TOO_SMALL, + SWITCH_STATUS_FOUND, SWITCH_STATUS_NOT_INITALIZED } switch_status_t; @@ -1684,12 +1685,27 @@ typedef switch_status_t (*switch_input_callback_function_t) (switch_core_session switch_input_type_t input_type, void *buf, unsigned int buflen); typedef switch_status_t (*switch_read_frame_callback_function_t) (switch_core_session_t *session, switch_frame_t *frame, void *user_data); typedef struct switch_say_interface switch_say_interface_t; + +struct switch_ivr_dmachine; +typedef struct switch_ivr_dmachine switch_ivr_dmachine_t; + +struct switch_ivr_dmachine_match { + switch_ivr_dmachine_t *dmachine; + const char *match_digits; + int32_t match_key; + void *user_data; +}; + +typedef struct switch_ivr_dmachine_match switch_ivr_dmachine_match_t; +typedef switch_status_t (*switch_ivr_dmachine_callback_t) (switch_ivr_dmachine_match_t *match); + typedef struct { switch_input_callback_function_t input_callback; void *buf; uint32_t buflen; switch_read_frame_callback_function_t read_frame_callback; void *user_data; + switch_ivr_dmachine_t *dmachine; } switch_input_args_t; typedef struct { diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 563706c9f2..560b1cd6ad 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -507,19 +507,19 @@ static switch_status_t caller_read_frame_callback(switch_core_session_t *session args.buflen = sizeof(buf); if (switch_ivr_play_file(session, NULL, cd->list[cd->index], &args) != SWITCH_STATUS_SUCCESS) { - return SWITCH_STATUS_FALSE; + return SWITCH_STATUS_BREAK; } if (match_key(caller_exit_key, *buf)) { cd->abort = 1; - return SWITCH_STATUS_FALSE; + return SWITCH_STATUS_BREAK; } cd->next = switch_epoch_time_now(NULL) + cd->freq; cd->index++; } } else if (cd->orbit_timeout && switch_epoch_time_now(NULL) >= cd->orbit_timeout) { cd->do_orbit = 1; - return SWITCH_STATUS_FALSE; + return SWITCH_STATUS_BREAK; } return SWITCH_STATUS_SUCCESS; @@ -540,7 +540,7 @@ static switch_status_t consumer_read_frame_callback(switch_core_session_t *sessi } if (total) { - return SWITCH_STATUS_FALSE; + return SWITCH_STATUS_BREAK; } return SWITCH_STATUS_SUCCESS; diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 7e7e8cda20..ef360d3148 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -224,7 +224,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session, switch_ivr_parse_all_events(session); - if (args && (args->input_callback || args->buf || args->buflen)) { + if (args && (args->input_callback || args->buf || args->buflen || args->dmachine)) { switch_dtmf_t dtmf; /* @@ -237,7 +237,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session, break; } switch_channel_dequeue_dtmf(channel, &dtmf); - if (args->input_callback) { + + if (args->dmachine) { + char ds[2] = {dtmf.digit, '\0'}; + if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } else if (args->input_callback) { status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen); } else { switch_copy_string((char *) args->buf, (void *) &dtmf, args->buflen); @@ -947,8 +953,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_s break; } + if (args && args->dmachine) { + if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } + if (read_frame && args && (args->read_frame_callback)) { - if (args->read_frame_callback(session, read_frame, args->user_data) != SWITCH_STATUS_SUCCESS) { + if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) { break; } } diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 4fe5732f82..1fee5f99ab 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -35,6 +35,281 @@ #include #include +struct switch_ivr_dmachine_binding { + char *digits; + int32_t key; + switch_ivr_dmachine_callback_t callback; + switch_byte_t is_regex; + void *user_data; + struct switch_ivr_dmachine_binding *next; +}; +typedef struct switch_ivr_dmachine_binding switch_ivr_dmachine_binding_t; + +#define DM_MAX_DIGIT_LEN 512 + +struct switch_ivr_dmachine { + switch_memory_pool_t *pool; + switch_byte_t my_pool; + uint32_t digit_timeout_ms; + uint32_t input_timeout_ms; + switch_ivr_dmachine_binding_t *binding_list; + switch_ivr_dmachine_binding_t *tail; + switch_ivr_dmachine_binding_t *last_matching_binding; + switch_ivr_dmachine_match_t match; + char digits[DM_MAX_DIGIT_LEN]; + char last_matching_digits[DM_MAX_DIGIT_LEN]; + uint32_t cur_digit_len; + uint32_t max_digit_len; + switch_time_t last_digit_time; + switch_byte_t is_match; +}; + +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_create(switch_ivr_dmachine_t **dmachine_p, + switch_memory_pool_t *pool, + uint32_t digit_timeout_ms, uint32_t input_timeout_ms) +{ + switch_byte_t my_pool = !!pool; + switch_ivr_dmachine_t *dmachine; + + if (digit_timeout_ms < 1 || input_timeout_ms < 1) return SWITCH_STATUS_FALSE; + + if (!pool) { + switch_core_new_memory_pool(&pool); + } + + dmachine = switch_core_alloc(pool, sizeof(*dmachine)); + dmachine->pool = pool; + dmachine->my_pool = my_pool; + dmachine->digit_timeout_ms = digit_timeout_ms; + dmachine->input_timeout_ms = input_timeout_ms; + dmachine->match.dmachine = dmachine; + *dmachine_p = dmachine; + + return SWITCH_STATUS_SUCCESS; +} + + +SWITCH_DECLARE(void) switch_ivr_dmachine_destroy(switch_ivr_dmachine_t **dmachine) +{ + switch_memory_pool_t *pool; + + if (!(dmachine && *dmachine)) return; + + pool = (*dmachine)->pool; + + if ((*dmachine)->my_pool) { + switch_core_destroy_memory_pool(&pool); + } +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_bind(switch_ivr_dmachine_t *dmachine, + const char *digits, + int32_t key, + switch_ivr_dmachine_callback_t callback, + void *user_data) +{ + switch_ivr_dmachine_binding_t *binding; + switch_size_t len; + + if (strlen(digits) > DM_MAX_DIGIT_LEN -1) { + return SWITCH_STATUS_FALSE; + } + + binding = switch_core_alloc(dmachine->pool, sizeof(*binding)); + if (*digits == '~') { + binding->is_regex = 1; + digits++; + } + binding->key = key; + binding->digits = switch_core_strdup(dmachine->pool, digits); + binding->callback = callback; + binding->user_data = user_data; + + if (dmachine->tail) { + dmachine->tail->next = binding; + } else { + dmachine->binding_list = binding; + } + + dmachine->tail = binding; + + len = strlen(digits); + + if (binding->is_regex && dmachine->max_digit_len != DM_MAX_DIGIT_LEN -1) { + dmachine->max_digit_len = DM_MAX_DIGIT_LEN -1; + } else if (len > dmachine->max_digit_len) { + dmachine->max_digit_len = (uint32_t) len; + } + + if (binding->is_regex) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "binding regex: %s key: %.4d callback: %p data: %p\n", + digits, key, (void *)(intptr_t) callback, user_data); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "binding digits: %4s key: %.4d callback: %p data: %p\n", + digits, key, (void *)(intptr_t) callback, user_data); + } + + return SWITCH_STATUS_SUCCESS; +} + +typedef enum { + DM_MATCH_NONE, + DM_MATCH_EXACT, + DM_MATCH_PARTIAL, + DM_MATCH_BOTH +} dm_match_t; + + +static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachine, switch_bool_t is_timeout) +{ + dm_match_t best = DM_MATCH_NONE; + switch_ivr_dmachine_binding_t *bp, *exact_bp = NULL; + int exact_count = 0, partial_count = 0, both_count = 0; + + + if (!dmachine->cur_digit_len) goto end; + + for(bp = dmachine->binding_list; bp; bp = bp->next) { + + if (bp->is_regex) { + switch_status_t r_status = switch_regex_match(dmachine->digits, bp->digits); + + if (r_status == SWITCH_STATUS_SUCCESS) { + if (is_timeout) { + best = DM_MATCH_EXACT; + exact_count++; + exact_bp = bp; + break; + } + + best = DM_MATCH_PARTIAL; + partial_count++; + continue; + } + } else { + if (!exact_bp && !strcmp(bp->digits, dmachine->digits)) { + exact_bp = bp; + best = DM_MATCH_EXACT; + exact_count++; + continue; + } + + if (!strncmp(dmachine->digits, bp->digits, strlen(dmachine->digits))) { + if (best == DM_MATCH_EXACT) { + if (is_timeout) { + best = DM_MATCH_EXACT; + exact_count++; + exact_bp = bp; + } else { + best = DM_MATCH_BOTH; + both_count++; + } + } else { + best = DM_MATCH_PARTIAL; + partial_count++; + } + break; + } + } + } + + end: + + if (!both_count && exact_bp) { + dmachine->last_matching_binding = exact_bp; + switch_set_string(dmachine->last_matching_digits, dmachine->digits); + best = DM_MATCH_EXACT; + } + + return best; + +} + +static switch_bool_t switch_ivr_dmachine_check_timeout(switch_ivr_dmachine_t *dmachine) +{ + switch_time_t now = switch_time_now(); + uint32_t timeout = dmachine->cur_digit_len ? dmachine->digit_timeout_ms : dmachine->input_timeout_ms; + + if ((uint32_t)((now - dmachine->last_digit_time) / 1000) > timeout) { + return SWITCH_TRUE; + } + + return SWITCH_FALSE; +} + +SWITCH_DECLARE(switch_ivr_dmachine_match_t *) switch_ivr_dmachine_get_match(switch_ivr_dmachine_t *dmachine) +{ + if (dmachine->is_match) { + dmachine->is_match = 0; + return &dmachine->match; + } + + return NULL; +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_match_t **match_p) +{ + switch_bool_t is_timeout = switch_ivr_dmachine_check_timeout(dmachine); + dm_match_t is_match = switch_ivr_dmachine_check_match(dmachine, is_timeout); + switch_status_t r; + + if (!dmachine->last_digit_time) { + r = SWITCH_STATUS_SUCCESS; + } else if (dmachine->cur_digit_len > dmachine->max_digit_len) { + r = SWITCH_STATUS_FALSE; + } else if (is_match == DM_MATCH_EXACT || (is_match == DM_MATCH_BOTH && is_timeout)) { + r = SWITCH_STATUS_FOUND; + + dmachine->match.match_digits = dmachine->last_matching_digits; + dmachine->match.match_key = dmachine->last_matching_binding->key; + dmachine->match.user_data = dmachine->last_matching_binding->user_data; + + if (dmachine->last_matching_binding->callback) { + dmachine->last_matching_binding->callback(&dmachine->match); + } + + if (match_p) { + *match_p = &dmachine->match; + } + + dmachine->is_match = 1; + } else if (is_timeout) { + r = SWITCH_STATUS_TIMEOUT; + } else if (dmachine->cur_digit_len == dmachine->max_digit_len) { + r = SWITCH_STATUS_NOTFOUND; + } else { + r = SWITCH_STATUS_SUCCESS; + } + + if (r != SWITCH_STATUS_SUCCESS) { + switch_ivr_dmachine_clear(dmachine); + } + + return r; +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_feed(switch_ivr_dmachine_t *dmachine, const char *digits, switch_ivr_dmachine_match_t **match) +{ + if (strlen(digits) + strlen(dmachine->digits) > dmachine->max_digit_len) { + return SWITCH_STATUS_FALSE; + } + + strncat(dmachine->digits, digits, dmachine->max_digit_len); + dmachine->cur_digit_len = strlen(dmachine->digits); + dmachine->last_digit_time = switch_time_now(); + + return switch_ivr_dmachine_ping(dmachine, match); +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_clear(switch_ivr_dmachine_t *dmachine) +{ + memset(dmachine->digits, 0, sizeof(dmachine->digits)); + dmachine->cur_digit_len = 0; + dmachine->last_digit_time = 0; + return SWITCH_STATUS_SUCCESS; +} + + #ifdef SWITCH_VIDEO_IN_THREADS struct echo_helper { switch_core_session_t *session; @@ -2528,7 +2803,7 @@ static void *SWITCH_THREAD_FUNC speech_thread(switch_thread_t *thread, void *obj if (status == SWITCH_STATUS_SUCCESS && switch_true(switch_channel_get_variable(channel, "asr_intercept_dtmf"))) { const char *p; - + if ((p = switch_stristr("", xmlstr))) { p += 7; } diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index d75af10a5e..c5b7a61000 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -493,7 +493,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se fh->pre_buffer_datalen = SWITCH_DEFAULT_FILE_BUFFER_LEN; } - if ((p = switch_channel_get_variable(channel, "RECORD_APPEND")) && switch_true(p)) { + if (switch_test_flag(fh, SWITCH_FILE_WRITE_APPEND) || ((p = switch_channel_get_variable(channel, "RECORD_APPEND")) && switch_true(p))) { file_flags |= SWITCH_FILE_WRITE_APPEND; } @@ -613,18 +613,24 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se break; } - if (args && (args->input_callback || args->buf || args->buflen)) { + if (args && (args->input_callback || args->buf || args->buflen || args->dmachine)) { /* dtmf handler function you can hook up to be executed when a digit is dialed during playback if you return anything but SWITCH_STATUS_SUCCESS the playback will stop. */ if (switch_channel_has_dtmf(channel)) { - if (!args->input_callback && !args->buf) { + if (!args->input_callback && !args->buf && !args->dmachine) { status = SWITCH_STATUS_BREAK; break; } switch_channel_dequeue_dtmf(channel, &dtmf); - if (args->input_callback) { + + if (args->dmachine) { + char ds[2] = {dtmf.digit, '\0'}; + if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } else if (args->input_callback) { status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen); } else { *((char *) args->buf) = dtmf.digit; @@ -651,8 +657,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se break; } + if (args && args->dmachine) { + if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } + if (args && (args->read_frame_callback)) { - if (args->read_frame_callback(session, read_frame, args->user_data) != SWITCH_STATUS_SUCCESS) { + if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) { break; } } @@ -810,16 +822,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi break; } + if (args && args->dmachine) { + if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } if (args && (args->read_frame_callback)) { - if (args->read_frame_callback(session, read_frame, args->user_data) != SWITCH_STATUS_SUCCESS) { + if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) { break; } } switch_ivr_parse_all_events(session); - if (args && (args->input_callback || args->buf || args->buflen)) { + if (args && (args->input_callback || args->buf || args->buflen || args->dmachine)) { /* dtmf handler function you can hook up to be executed when a digit is dialed during gentones if you return anything but SWITCH_STATUS_SUCCESS the playback will stop. @@ -831,7 +848,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi break; } switch_channel_dequeue_dtmf(channel, &dtmf); - if (args->input_callback) { + + if (args->dmachine) { + char ds[2] = {dtmf.digit, '\0'}; + if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } else if (args->input_callback) { status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen); } else { *((char *) args->buf) = dtmf.digit; @@ -841,7 +864,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi if (args->input_callback) { switch_event_t *event; - + if (switch_core_session_dequeue_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { status = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen); switch_event_destroy(&event); @@ -1224,7 +1247,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess switch_ivr_parse_all_events(session); - if (args && (args->input_callback || args->buf || args->buflen)) { + if (args && (args->input_callback || args->buf || args->buflen || args->dmachine)) { /* dtmf handler function you can hook up to be executed when a digit is dialed during playback if you return anything but SWITCH_STATUS_SUCCESS the playback will stop. @@ -1236,7 +1259,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess break; } switch_channel_dequeue_dtmf(channel, &dtmf); - if (args->input_callback) { + + if (args->dmachine) { + char ds[2] = {dtmf.digit, '\0'}; + if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } else if (args->input_callback) { status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen); } else { *((char *) args->buf) = dtmf.digit; @@ -1405,10 +1434,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess break; } + if (args && args->dmachine) { + if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } + if (args && (args->read_frame_callback)) { int ok = 1; switch_set_flag(fh, SWITCH_FILE_CALLBACK); - if (args->read_frame_callback(session, read_frame, args->user_data) != SWITCH_STATUS_SUCCESS) { + if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) { ok = 0; } switch_clear_flag(fh, SWITCH_FILE_CALLBACK); @@ -1919,7 +1954,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session switch_event_destroy(&event); } - if (args && (args->input_callback || args->buf || args->buflen)) { + if (args && (args->input_callback || args->buf || args->buflen || args->dmachine)) { /* dtmf handler function you can hook up to be executed when a digit is dialed during playback * if you return anything but SWITCH_STATUS_SUCCESS the playback will stop. */ @@ -1933,7 +1968,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session status = SWITCH_STATUS_BREAK; } else { switch_channel_dequeue_dtmf(channel, &dtmf); - if (args->input_callback) { + + if (args->dmachine) { + char ds[2] = {dtmf.digit, '\0'}; + if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } else if (args->input_callback) { status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen); } else { *((char *) args->buf) = dtmf.digit; @@ -1972,9 +2013,15 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session break; } + if (args && args->dmachine) { + if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) { + goto done; + } + } + if (args && (args->read_frame_callback)) { - if (args->read_frame_callback(session, read_frame, args->user_data) != SWITCH_STATUS_SUCCESS) { - break; + if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) { + goto done; } } } @@ -2038,15 +2085,23 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session break; } + if (args && args->dmachine) { + if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) { + goto done; + } + } + if (args && (args->read_frame_callback)) { - if (args->read_frame_callback(session, read_frame, args->user_data) != SWITCH_STATUS_SUCCESS) { - break; + if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) { + goto done; } } } } + done: + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "done speaking text\n"); flags = 0; switch_core_speech_flush_tts(sh); From be3d61dead30742a3d941ae6351568f800148e03 Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Mon, 4 Oct 2010 18:05:30 -0700 Subject: [PATCH 6/7] Update ChangeLog through Sept 21 (more coming) --- docs/ChangeLog | 55 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/docs/ChangeLog b/docs/ChangeLog index a2ed493f37..412ab9ff18 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -16,12 +16,16 @@ freeswitch (1.0.7) build: VS 2010 - Change to V4 framework, add SWIG v2.0 files to fix release build exceptions(temp fix till we upgrade all SWIG files) (r:812f4309) build: Windows VS2010 build - remove strange characters (r:ba1546e0/FSBUILD-297) build: Make bootstrap.sh Bourne shell compatible (r:8dbd62ff/FSBUILD-301) + codec2: working prototype, still for testing only (r:04ca0751) config: move limit.conf to db.conf config: Update VM phrase macros to voice option then action on main, config menus config: Remove 99xx extension numbers to avoid dp conflicts (r:0c9bb174/DP-17) config: update config example for caller-id-type (r:8f03a7cd) config: default to 48k since most sound cards can do that (r:170404a4) config: Create RFC2822_DATE for use in emails. Some clients fail to sort emails properly without a Date: line. (r:a1f19d91) + config: move enum to the bottom of default. (r:4d448c97) + config: Add att_xfer example to default dialplan (r:20ec962a) + config: default example to resolve some issues with SCA in cases where host and ip are mixed causing the phone to be confused. (r:0279261b) core: Add RTCP support (FSRTP-14) core: handle some errors on missing db handle conditions core: add ... and shutdown as a fail-safe when no modules are loaded @@ -78,8 +82,22 @@ freeswitch (1.0.7) core: Implemented 'Block Fork' and removed possibility for "-nc -nf" potential issue. (r:f26a6972/FSCORE-652) core: Add console callback for listing loaded/available modules for load/unload/reload commands (r:d68a1218/FSCORE-662) core: strip trailing and leading whitespace in api execute args and commands (r:ca481842) + core: Fix SQLLEN to prevent queue buffer overrun (r:68d1c32a/FS-2149) + core: add origination_caller_profile to log all attempted calls for a paticular leg (r:977a8ad7) + core: Add attribute "path" to autoload_configs/modules.conf.xml entry. (r:1a75821d) + core: add tone2wav (r:6f2c455f) + core: add speed boost to sql thread (r:ef79535c) + core: reverse the linked list in ivr menus to support accidental feature of multiple entries for the same keys (r:d4a01324) + core: Add time of day string compare function switch_tod_cmp. It usable in XML dialplan with time-of-day. String format is hh:mm:ss you can define a range like this : 09:00-17:00 (Second are not optional) (r:4ab8fa13) + core: Add date time range string compare function switch_fulldate_cmp. It usable in XML dialplan with date-time. String format example : 2009-10-10 14:33:22~2009-11-10 17:32:31. (r:c9fcce08) + core: Add day of week 3 letter initial usage in "wday" field in the dialplan. Example : mon-fri. Using number as before is still supported. Several public switch function are available. (r:59ec8ced) + core: set conditionals to only fire when the mutex can be obtained (r:07ec7867) + core: avoid segfault when sofia tries to update the callee id at the same time as the outbound call is transferred (r:df63657e) + core: make code more automagic to shut up the dude on the list (r:d093a4a4) + core: Fix memory leak if we fail to enqueue new event to EVENT_QUEUE in switch_event.c (r:ef773e07/FS-2148) lang: Improve French phrase files (FSCONFIG-23) libdingaling: fix race on shutdown causing crash (FSMOD-47) + libdingaling: Fix crash in new GV interface when exceeding 24 calls (r:be00609a/FS-2171) libesl: Fix potential race condition (ESL-36) libesl: Add /uuid command to fs_cli to filter logs by uuid libesl: Increase buffer in fs_cli for Win (r:d1d6be88/FSCORE-611) @@ -93,6 +111,8 @@ freeswitch (1.0.7) libesl: Fix SEGV when using serialize function without any arguments (r:910729b5/ESL-44) libesl: fix leak-on-error in esl_connect_timeout() (r:4263d60e) libfreetdm: implemented freetdm config nodes and ss7 initial configuration + libfreetdm: fix codec for CAS signaling (r:b76e7f18) + libfreetdm: freetdm: ss7- added support for incoming group blocks, started adding support for ansi (r:c219a73c) libopenzap: Add CLI tracing libs: Merged OpenZAP and FreeTDM into the FreeSWITCH tree. libs: Add support for TLS on Windows using openssl (r:1abe3b93/MODSOFIA-92) @@ -103,6 +123,7 @@ freeswitch (1.0.7) libspandsp: removed a saturate16 from spandsp that was causing problems fixed a typo in the MSVC inttypes.h file for spandsp libspandsp: Changes to the signaling tone detector to detect concurrent 2400Hz + 2600Hz tones. This passes voice immunity and other key tests, but it bounces a bit when transitions like 2400 -> 2400+2600 -> 2600 occur. Transitions between tone off and tone on are clean. (r:bc13e944) libspandsp: Fix Windows build after libspandsp update (r:d70cc852/FSBUILD-293) + libspandsp: Fix for T.30 processing of operator interrupts, to improve compatibility with some machines, which seem to send them when no operator is around. (r:84ee0ae6) mod_avmd: Initial check in - Advanced Voicemail Detect (r:10c6a30a) (by Eric Des Courtis) mod_avmd: Add to windows build (r:df4bd935) mod_callcenter: Initial commit of the mod_callcenter application. This module is in it early state of developpement. You can see documentation on the wiki at : http://wiki.freeswitch.org/wiki/Mod_callcenter For support/comments, please use http://jira.freeswitch.org/ and select the MOD CALLCENTER module. (r:ba09b96d) @@ -116,7 +137,8 @@ freeswitch (1.0.7) mod_callcenter: You can now allow caller that have hangup before agent answer to call back and resume their previous position. (r:ab2529d4) mod_callcenter: correct multiple little things following the recent tiers and join back features (r:9b33bd1c) mod_callcenter: Add more channel variable and event and fix a mem leak (r:2d3d8c8d) - od_callcenter: Make more sence to bridge the caller to the agent. Before, in the xml_cdr you saw it it like the agent initiated the call to the member (r:0be95658) + mod_callcenter: Make more sence to bridge the caller to the agent. Before, in the xml_cdr you saw it it like the agent initiated the call to the member (r:0be95658) + mod_callcenter: Added max-wait-time and max-wait-time-with-no-agent param to a queue. (r:3482f95e) mod_cidlookup: null xml is bad (r:095815f8) mod_cid_lookup: honor skipcitystate when using whitepages (r:a66654de/FSMOD-53) mod_commands: make break uuid_break and add cascade flag @@ -127,6 +149,9 @@ freeswitch (1.0.7) mod_commands: Fix a segfault if no arguments is provided to limit_hash_usage (r:8ceb2a9b) mod_commands: fsctl max_session should display int, not float (r:f7e2410e/FSCORE-634) mod_commands: limit - reset rate and release resource apis Thanks Moy (r:a7c31e6f/FSCORE-637) + mod_commands: Fix user_data returning the first value found instead of the last. Also add support to get variable from the group. (r:402f2391) + mod_commands: Allow cond API to return empty false value (r:c8a897b9) + mod_commands: ***BEHAVIOUR CHANGE*** reloadacl, load , reload will now explicitly call reloadxml (r:42c9df72) mod_conference: Fix reporting of volume up/down (MODAPP-419) mod_conference: add last talking time per member to conference xml list mod_conference: add terminate-on-silence conference param @@ -139,6 +164,8 @@ freeswitch (1.0.7) mod_dingaling: make mod_dingaling compat with google's new free phonecalls thing (r:ba0a2a32) mod_dingaling: make dingaling work with google voice inbound too (r:4ee68141) mod_dingaling: Fix crash when testing the new gv-dingaling with around 24 concurrent calls (r:73e1ec5e/FSCORE-667) + mod_dingaling: Fix NULL pointer (r:e3eff816/FS-1103) + mod_directory: Add variable directory_search_order to allow to search by first name by default is set to "first_name" (r:163ca31f) mod_db: fix stack corruption (MODAPP-407) mod_dptools: add eavesdrop_enable_dtmf chan var (r:596c0012) mod_dptools: Make park app not send 183 session progress (r:76932995/FSCORE-567) @@ -153,6 +180,7 @@ freeswitch (1.0.7) mod_fifo: cancel outbound call if customer hangs up (r:cadb4d94) mod_fifo: add taking_calls param to fifo member add and config file (r:821488bf) mod_fifo: add nomedia flag (r:2d30a8c2) + mod_fifo: Fix inconsistency between the fifo queue and the channels (num callers in queue can become "-1") (r:07487114/FS-1659) mod_freetdm: Fix for TON and NPI not passed through to channel variables on incoming calls mod_freetdm: add pvt data to freetdm channels fix fxs features (r:9d456900) mod_freetdm: export and import boost custom data (r:edb2d582) @@ -213,9 +241,14 @@ freeswitch (1.0.7) mod_lcr: fix dialplan issues with default profile and logging when no caller_profile set (r:00170558) mod_lcr: assign default profile even if testing is skipped (r:6420099c) mod_lcr: fix compiler warning on newer gcc (r:bfa414cb) + mod_lcr: don't count twice (r:eaeabc7b/FS-1810) mod_loopback: add loopback_bowout_on_execute var to make 1 legged loopback calls bow out of the picture mod_loopback: only execute app once in app mode (r:64f58f2d) + mod_lua: Add switch_core_sqldb functionality from inside Lua script (r:26f2e095/FS-1384) + mod_lua: Made 2nd arg to freeswitch.Dbh:query (cb func) optional (r:87db11af) + mod_lua: Added SAF_ROUTING_EXEC flag to lua app, so it can be run inline (r:7d5ca1c0) mod_managed: Added wrapper for switch_event_bind for .net (r:a5f07a80/MODLANG-165) + mod_managed: add additional support (r:5be58aac) mod_mp4v: MP4V-ES passthru for washibechi on IRC mod_nibblebill: free allocated mem at shutdown; free properly if using custom_sql mod_nibblebill: Add SAF_SUPPORT_NOMEDIA to nibblebill @@ -303,12 +336,28 @@ freeswitch (1.0.7) mod_sofia: Fix memleak and mwi event not generated on first register (r:04b9b3e2) mod_sofia: when getting presence with no payload consider it an extension to the expires time in the dialog (r:70331e88) mod_sofia: don't put blank 'version' attr in dialog-info packets (r:749dc864) + mod_sofia: speed up db action in sofia recover (r:8114b3f1) + mod_sofia: Support display updates for Cisco SIP endpoints (tested on SPA series) (r:ac205288/FS-884) + mod_sofia: dont put an rpid in 183 or 200 if pass-callee-id is false (r:86de47ff) + mod_sofia: improve sofia recover in some nat cases (r:4526ba30) + mod_sofia: edge cases for sofia recover (r:646a5609) + mod_sofia: Correct the order what param and variables are overriding them self in user/group/domain (r:5a6f0f5c) + mod_sofia: include accumulated stats from rtcp into vars (r:d5ff3e04) + mod_sofia: make sure hold-related code is skipped 100% with disable-hold set (r:403bf6af) + mod_sofia: make force-subscription-expires only work on nonzero expire deltas, 0 means unscubscribe (r:b7751868) + mod_sofia: presence tweaks and addition of all-reg-options-ping which is like nat-options-ping only for every registered host (r:04b52156) + mod_sofia: If sip_invite_domain is used lets use it for rpid_domain no matter what because I know best if I set it (r:8726104a) + mod_sofia: add inline lists for tab complete db using ::[a:b syntax (r:445731ee) + mod_sofia: add sofia profile gwlist up|down to list up or downed profiles for feeding into mod distributor to exclude dead gateways (r:0477cb67) + mod_sofia: add 'sofia global siptrace on' so we don't have to always teach people to enable sip trace on each profile (r:09fa6678) mod_spandsp: initial checkin of mod_fax/mod_voipcodecs merge into mod_spandsp (r:fa9a59a8) mod_spandsp: rework of new mod_spandsp to have functions broken up into different c files (r:65400642) mod_spandsp: improve duplicate digit detection and add 'min_dup_digit_spacing_ms' channel variable for use with the dtmf detector (r:eab4f246/FSMOD-45) mod_spandsp: add start_tone_detect/stop_tone_detect app and api commands for tone and cadence detection (r:a6e65147/MODAPP-378) mod_spandsp: Fix mod_spandsp receive t38 fax error in windows7 (r:fca93f29/MODAPP-443) mod_spandsp: Moved spandsp to a more recent version. A huge number of little changes occur here, as recently spandsp lost all the $Id$ entries the source files had for the dark old days of CVS (r:f029f7ef) + mod_spandsp: move app flag into 'T38' namespace for the sake of housekeeping (r:0d0b4b43) + mod_spandsp: make t38 terminal mode more reliable (r:83da7bd3) mod_spidermonkey: allow vars to be set containing vars from languages (r:5cd072a3) mod_spidermonkey: fix seg in js hangup (r:7d554c11) mod_spidermonkey: Fix mod_spidermonkey build on FreeBSD, (Undefined symbol PR_LocalTimeParameters). (r:3edb8419) @@ -322,10 +371,14 @@ freeswitch (1.0.7) mod_voicemail: fix vm msg being deleted when pressing key to forward to email (MODAPP-403) mod_voicemail: make voicemails use the uuid of the channel who recorded it when applicable (r:98a5a30a) mod_voicemail: user unable to play or delete voicemail via web API (r:b5205c0b/MODAPP-447) + mod_voicemail: Allow to forward a message or send it via email key during the playback of the recording, not just when the menu is playing. (r:83aeda79) + mod_voicemail: fix vm_inject to a group and change syntax for sending to a whole domain to domain= for clarity sake (r:f30a1cc6) + mod_voicemail: add quotes to vm_cc command generated internally to escape spaces in the caller id name (r:5f012813) mod_xml_cdr: add force_process_cdr var to process b leg cdr on a case by case basis when b leg cdr is disabled (XML-17) mod_xml_cdr: add leg param to query string (XML-24) mod_xml_cdr: fix locked sessions (XML-26) mod_xml_cdr: fix minor memory leaks and config bug (r:19253d83/MODEVENT-62) + mod_xml_rpc: Fix crash if unauthorized XML RPC is attempted (r:9835395c/FS-184) sofia-sip: fix null derefernce segfault in soa (r:f356c5e6) sofia-sip: extend timeout for session expires on short timeouts to be 90% of timeout instead of 1/3 to handle devices that do not refresh in time such as polycom (r:a7f48928/SFSIP-212) From 4f414765ee55a59ecd408a774aadf04fdaa83f28 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Mon, 4 Oct 2010 17:31:33 -0400 Subject: [PATCH 7/7] mod_sangoma_codec: fix memory leak by using a memory pool per transcoding session --- .../mod_sangoma_codec/mod_sangoma_codec.c | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c index d2e1e1c357..ae7468ebcc 100644 --- a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c +++ b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c @@ -199,6 +199,8 @@ static int sangoma_create_rtp_port(void *usr_priv, uint32_t host_ip, uint32_t *p static int sangoma_create_rtp(void *usr_priv, sngtc_codec_request_leg_t *codec_req_leg, sngtc_codec_reply_leg_t* codec_reply_leg, void **rtp_fd) { + switch_status_t status; + switch_memory_pool_t *sesspool = NULL; switch_rtp_t *rtp_session = NULL; char codec_ip[255]; switch_rtp_flag_t flags = 0; @@ -208,6 +210,18 @@ static int sangoma_create_rtp(void *usr_priv, sngtc_codec_request_leg_t *codec_r char local_ip[255]; switch_port_t rtp_port; struct sangoma_transcoding_session *sess = usr_priv; + + /* + * We *MUST* use a new pool + * Do not use the session pool since the session may go away while the RTP socket should linger around + * until sangoma_transcode decides to kill it (possibly because the same RTP session is used for a different call) + * also do not use the module pool otherwise memory would keep growing because switch_rtp_destroy does not + * free the memory used (is assumed it'll be freed when the pool is destroyed) + */ + status = switch_core_new_memory_pool(&sesspool); + if (status != SWITCH_STATUS_SUCCESS) { + return -1; + } rtp_port = (switch_port_t)(long)*rtp_fd; @@ -222,20 +236,20 @@ static int sangoma_create_rtp(void *usr_priv, sngtc_codec_request_leg_t *codec_r local_ip, rtp_port, codec_ip, codec_reply_leg->codec_udp_port, iana, codec_req_leg->ms*1000, sess->sessid); - /* create the RTP socket, dont use the session pool since the session may go away while the RTP socket should linger around - * until sangoma_transcode decides to kill it (possibly because the same RTP session is used for a different call) */ + /* create the RTP socket */ rtp_session = switch_rtp_new(local_ip, rtp_port, codec_ip, codec_reply_leg->codec_udp_port, iana, sess->impl->samples_per_packet, codec_req_leg->ms * 1000, /* microseconds per packet */ - flags, NULL, &err, g_pool); + flags, NULL, &err, sesspool); if (!rtp_session) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create switch rtp session: %s\n", err); + switch_core_destroy_memory_pool(&sesspool); return -1; } - + switch_rtp_set_private(rtp_session, sesspool); *rtp_fd = rtp_session; return 0; @@ -243,8 +257,11 @@ static int sangoma_create_rtp(void *usr_priv, sngtc_codec_request_leg_t *codec_r static int sangoma_destroy_rtp(void *usr_priv, void *fd) { + switch_memory_pool_t *sesspool; switch_rtp_t *rtp = fd; + sesspool = switch_rtp_get_private(rtp); switch_rtp_destroy(&rtp); + switch_core_destroy_memory_pool(&sesspool); return 0; } @@ -406,6 +423,7 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec sess->encoder.tx++; /* do the reading */ + memset(&encoded_frame, 0, sizeof(encoded_frame)); for ( ; ; ) { sres = switch_rtp_zerocopy_read_frame(sess->encoder.rxrtp, &encoded_frame, SWITCH_IO_FLAG_NOBLOCK); if (sres == SWITCH_STATUS_GENERR) { @@ -525,6 +543,7 @@ static switch_status_t switch_sangoma_decode(switch_codec_t *codec, /* codec ses sess->decoder.tx++; /* do the reading */ + memset(&ulaw_frame, 0, sizeof(ulaw_frame)); for ( ; ; ) { sres = switch_rtp_zerocopy_read_frame(sess->decoder.rxrtp, &ulaw_frame, SWITCH_IO_FLAG_NOBLOCK); if (sres == SWITCH_STATUS_GENERR) {