From 5df64c1d3836ada341075cf5d3a7db55cae702cd Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 25 Feb 2010 23:36:18 +0000 Subject: [PATCH] merged 1023:1039 http://svn.openzap.org/svn/openzap/trunk git-svn-id: http://svn.openzap.org/svn/openzap/branches/sangoma_boost@1040 a93c3328-9c30-0410-af19-c9cd2b2d52af --- libs/freetdm/mod_freetdm/mod_freetdm.c | 7 +- libs/freetdm/src/ftdm_io.c | 4 +- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 2 - .../ftmod_sangoma_boost/ftmod_sangoma_boost.c | 155 +++++++++++++++--- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 16 +- libs/freetdm/src/include/ftdm_types.h | 3 + 6 files changed, 151 insertions(+), 36 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 496131a213..8a19d3d725 100644 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -675,7 +675,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch tech_pvt->read_frame.samples /= 2; } - if (ftdm_channel_dequeue_dtmf(tech_pvt->ftdmchan, dtmf, sizeof(dtmf))) { + while (ftdm_channel_dequeue_dtmf(tech_pvt->ftdmchan, dtmf, sizeof(dtmf))) { switch_dtmf_t _dtmf = { 0, SWITCH_DEFAULT_DTMF_DURATION }; char *p; for (p = dtmf; p && *p; p++) { @@ -737,10 +737,11 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc wflags = FTDM_WRITE; - status = ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, tech_pvt->ftdmchan->effective_interval * 4); + status = ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, tech_pvt->ftdmchan->effective_interval * 10); if (!(wflags & FTDM_WRITE)) { - goto fail; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Dropping frame! (write not ready)\n"); + return SWITCH_STATUS_SUCCESS; } len = frame->datalen; diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index d81737886b..2ea9ad7d77 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -1322,9 +1322,7 @@ static ftdm_status_t ftdm_channel_reset(ftdm_channel_t *ftdmchan) memset(ftdmchan->tokens, 0, sizeof(ftdmchan->tokens)); ftdmchan->token_count = 0; - if (ftdmchan->dtmf_buffer) { - ftdm_buffer_zero(ftdmchan->dtmf_buffer); - } + ftdm_channel_flush_dtmf(ftdmchan); if (ftdmchan->gen_dtmf_buffer) { ftdm_buffer_zero(ftdmchan->gen_dtmf_buffer); diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 758942452e..85fe09f7bc 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -239,7 +239,6 @@ static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, cons { ftdm_sigmsg_t sigev; ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_r2_data_t *r2data = ftdmchan->span->signal_data; ftdm_log(FTDM_LOG_NOTICE, "Call offered on chan %d, ANI = %s, DNIS = %s, Category = %s\n", openr2_chan_get_number(r2chan), ani, dnis, openr2_proto_get_category_string(category)); @@ -910,7 +909,6 @@ static void *ftdm_r2_channel_run(ftdm_thread_t *me, void *obj) ftdm_sigmsg_t sigev; ftdm_channel_t *ftdmchan = (ftdm_channel_t *)obj; openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan; - ftdm_r2_data_t *r2data = ftdmchan->span->signal_data; ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_INTHREAD); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c index 88e19454de..53e1beb9b4 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c @@ -111,7 +111,6 @@ static uint16_t SETUP_GRID[FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN+1][FTDM_MAX_ static sangoma_boost_request_t OUTBOUND_REQUESTS[MAX_REQ_ID+1] = {{ 0 }}; static ftdm_mutex_t *request_mutex = NULL; -static ftdm_mutex_t *signal_mutex = NULL; static uint8_t req_map[MAX_REQ_ID+1] = { 0 }; static uint8_t nack_map[MAX_REQ_ID+1] = { 0 }; @@ -219,7 +218,6 @@ static ftdm_channel_t *find_ftdmchan(ftdm_span_t *span, sangomabc_short_event_t targetchan = event->chan; } - ftdm_mutex_lock(signal_mutex); for(i = 1; i <= span->chan_count; i++) { if (span->channels[i]->physical_span_id == targetspan && span->channels[i]->physical_chan_id == targetchan) { ftdmchan = span->channels[i]; @@ -237,7 +235,6 @@ static ftdm_channel_t *find_ftdmchan(ftdm_span_t *span, sangomabc_short_event_t } } } - ftdm_mutex_unlock(signal_mutex); return ftdmchan; } @@ -273,7 +270,12 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request) ftdm_status_t status = FTDM_FAIL; sangoma_boost_request_id_t r; sangomabc_event_t event = {0}; - int boost_request_timeout = 5000; + /* sanity has to be more than 8 seconds. + * In PRI specs, timeout is 4 seconds for remote switch to respond to a SETUP, + * and PRI stack will retransmit a second SETUP after the first timeout, so + * we should allow for at least 8 seconds. + */ + int boost_request_timeout = 10000; sangoma_boost_request_status_t st; char dnis[128] = ""; char *gr = NULL; @@ -864,18 +866,8 @@ static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, s ftdm_channel_t *ftdmchan; if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) { - if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) { - ftdm_log(FTDM_LOG_CRIT, "START CANT FIND CHAN %d:%d AT ALL\n", event->span+1,event->chan+1); - goto error; - } - /* this handles race conditions where state handlers are still pending to be executed for finished calls - but an incoming call arrives first, we must complete the channel states and then try again to get the - ftdm channel */ - advance_chan_states(ftdmchan); - if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) { - ftdm_log(FTDM_LOG_CRIT, "START CANT FIND CHAN %d:%d EVEN AFTER STATE ADVANCE\n", event->span+1,event->chan+1); - goto error; - } + ftdm_log(FTDM_LOG_CRIT, "START CANT FIND CHAN %d:%d\n", event->span+1,event->chan+1); + goto error; } if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { @@ -931,6 +923,48 @@ static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, s } +static void handle_call_loop_start(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event) +{ + ftdm_status_t res = FTDM_FAIL; + ftdm_channel_t *ftdmchan; + + if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) { + ftdm_log(FTDM_LOG_CRIT, "CANNOT START LOOP, CHAN NOT AVAILABLE %d:%d\n", event->span+1,event->chan+1); + return; + } + + if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_CRIT, "CANNOT START LOOP, CANT OPEN CHAN %d:%d\n", event->span+1,event->chan+1); + return; + } + + ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP, 0, res); + if (res != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_CRIT, "yay, could not set the state of the channel to IN_LOOP, loop will fail\n"); + ftdm_channel_done(ftdmchan); + return; + } + ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_LOOP, NULL); +} + +static void handle_call_loop_stop(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event) +{ + ftdm_channel_t *ftdmchan; + ftdm_status_t res = FTDM_FAIL; + if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) { + ftdm_log(FTDM_LOG_CRIT, "CANNOT STOP LOOP, INVALID CHAN REQUESTED %d:%d\n", event->span+1,event->chan+1); + return; + } + if (ftdmchan->state != FTDM_CHANNEL_STATE_IN_LOOP) { + ftdm_log(FTDM_LOG_ERROR, "Got stop loop request in a channel that is not in loop, ignoring ...\n"); + return; + } + ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); + /* even when we did not sent a msg we set this flag to avoid sending call stop in the DOWN state handler */ + ftdm_set_flag(ftdmchan, SFLAG_SENT_FINAL_MSG); + ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_DOWN, 0, res); +} + /** * \brief Handler for heartbeat event * \param mcon sangoma boost connection @@ -1015,6 +1049,53 @@ static void handle_incoming_digit(sangomabc_connection_t *mcon, ftdm_span_t *spa return; } + +/** + * \brief Checks if span has state changes pending and processes + * \param span Span where event was fired + * \param event Event to handle + * \return The locked FTDM channel associated to the event if any, NULL otherwise + */ +static ftdm_channel_t* event_process_states(ftdm_span_t *span, sangomabc_short_event_t *event) +{ + ftdm_channel_t *ftdmchan = NULL; + + switch (event->event_id) { + case SIGBOOST_EVENT_CALL_START_NACK: + case SIGBOOST_EVENT_CALL_START_NACK_ACK: + if (event->call_setup_id) { + return NULL; + } + //if event->span and event->chan is valid, fall-through + case SIGBOOST_EVENT_CALL_START: + case SIGBOOST_EVENT_CALL_START_ACK: + case SIGBOOST_EVENT_CALL_STOPPED: + case SIGBOOST_EVENT_CALL_PROGRESS: + case SIGBOOST_EVENT_CALL_ANSWERED: + case SIGBOOST_EVENT_CALL_STOPPED_ACK: + case SIGBOOST_EVENT_DIGIT_IN: + case SIGBOOST_EVENT_INSERT_CHECK_LOOP: + case SIGBOOST_EVENT_REMOVE_CHECK_LOOP: + if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) { + ftdm_log(FTDM_LOG_DEBUG, "PROCESS STATES CANT FIND CHAN %d:%d\n", event->span+1,event->chan+1); + return NULL; + } + break; + case SIGBOOST_EVENT_HEARTBEAT: + case SIGBOOST_EVENT_SYSTEM_RESTART_ACK: + case SIGBOOST_EVENT_SYSTEM_RESTART: + case SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE: + return NULL; + default: + ftdm_log(FTDM_LOG_CRIT, "Unhandled event id:%d\n", event->event_id); + return NULL; + } + + ftdm_mutex_lock(ftdmchan->mutex); + advance_chan_states(ftdmchan); + return ftdmchan; +} + /** * \brief Handler for sangoma boost event * \param span Span where event was fired @@ -1023,14 +1104,19 @@ static void handle_incoming_digit(sangomabc_connection_t *mcon, ftdm_span_t *spa */ static int parse_sangoma_event(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event) { - ftdm_mutex_lock(signal_mutex); + ftdm_channel_t* ftdmchan = NULL; if (!ftdm_running()) { ftdm_log(FTDM_LOG_WARNING, "System is shutting down.\n"); - goto end; + return -1; } ftdm_assert_return(event->call_setup_id <= MAX_REQ_ID, -1, "Unexpected call setup id\n"); + + /* process all pending state changes for that channel before + * processing the new boost event */ + ftdmchan = event_process_states(span, event); + switch(event->event_id) { case SIGBOOST_EVENT_CALL_START: handle_call_start(span, mcon, (sangomabc_event_t*)event); @@ -1064,10 +1150,10 @@ static int parse_sangoma_event(ftdm_span_t *span, sangomabc_connection_t *mcon, nack_map[event->call_setup_id] = 0; break; case SIGBOOST_EVENT_INSERT_CHECK_LOOP: - //handle_call_loop_start(event); + handle_call_loop_start(span, mcon, event); break; case SIGBOOST_EVENT_REMOVE_CHECK_LOOP: - //handle_call_stop(event); + handle_call_loop_stop(span, mcon, event); break; case SIGBOOST_EVENT_SYSTEM_RESTART_ACK: handle_restart_ack(mcon, span, event); @@ -1086,11 +1172,13 @@ static int parse_sangoma_event(ftdm_span_t *span, sangomabc_connection_t *mcon, break; } - end: - - ftdm_mutex_unlock(signal_mutex); + if(ftdmchan != NULL) { + advance_chan_states(ftdmchan); + ftdm_mutex_unlock(ftdmchan->mutex); + } return 0; + } /** @@ -1290,6 +1378,11 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) status = ftdm_span_send_signal(ftdmchan->span, &sig); } break; + case FTDM_CHANNEL_STATE_IN_LOOP: + { + /* nothing to do, we sent the FTDM_COMMAND_ENABLE_LOOP command in handle_call_loop_start() right away */ + } + break; default: break; } @@ -1297,13 +1390,11 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) static __inline__ void advance_chan_states(ftdm_channel_t *ftdmchan) { - ftdm_mutex_lock(ftdmchan->mutex); while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); state_advance(ftdmchan); ftdm_channel_complete_state(ftdmchan); } - ftdm_mutex_unlock(ftdmchan->mutex); } /** @@ -1668,7 +1759,6 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_boost_init) return FTDM_FAIL; } ftdm_mutex_create(&request_mutex); - ftdm_mutex_create(&signal_mutex); ftdm_mutex_create(&g_boost_modules_mutex); memset(&g_trunkgroups[0], 0, sizeof(g_trunkgroups)); return FTDM_SUCCESS; @@ -1693,7 +1783,6 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_boost_destroy) hashtable_destroy(g_boost_modules_hash); ftdm_mutex_destroy(&request_mutex); - ftdm_mutex_destroy(&signal_mutex); ftdm_mutex_destroy(&g_boost_modules_mutex); return FTDM_SUCCESS; } @@ -1811,6 +1900,18 @@ static ftdm_state_map_t boost_state_map = { {FTDM_CHANNEL_STATE_RESTART, FTDM_END}, {FTDM_CHANNEL_STATE_DOWN, FTDM_END} }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_DOWN}, + {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_IN_LOOP}, + {FTDM_CHANNEL_STATE_DOWN, FTDM_END} + }, { ZSD_INBOUND, ZSM_UNACCEPTABLE, diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index 9e66d8ec53..c7723e94a9 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -497,6 +497,10 @@ static FIO_OPEN_FUNCTION(wanpipe_open) wanpipe_tdm_api_t tdm_api; memset(&tdm_api,0,sizeof(tdm_api)); + sangoma_tdm_flush_bufs(ftdmchan->sockfd, &tdm_api); +#ifdef LIBSANGOMA_VERSION + sangoma_flush_event_bufs(ftdmchan->sockfd, &tdm_api); +#endif if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) { ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE; @@ -605,6 +609,14 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) //code me } break; + case FTDM_COMMAND_ENABLE_LOOP: + { + // code me + } + case FTDM_COMMAND_DISABLE_LOOP: + { + // code me + } case FTDM_COMMAND_SET_INTERVAL: { err=sangoma_tdm_set_usr_period(ftdmchan->sockfd, &tdm_api, FTDM_COMMAND_OBJ_INT); @@ -1051,7 +1063,9 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event) if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_STOP) { ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_MUTE); - ftdm_channel_queue_dtmf(ftdmchan, tmp_dtmf); + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { + ftdm_channel_queue_dtmf(ftdmchan, tmp_dtmf); + } } } break; diff --git a/libs/freetdm/src/include/ftdm_types.h b/libs/freetdm/src/include/ftdm_types.h index d1b3a4f711..776ec07367 100644 --- a/libs/freetdm/src/include/ftdm_types.h +++ b/libs/freetdm/src/include/ftdm_types.h @@ -315,6 +315,8 @@ typedef enum { FTDM_COMMAND_SET_PRE_BUFFER_SIZE, FTDM_COMMAND_SET_LINK_STATUS, FTDM_COMMAND_GET_LINK_STATUS, + FTDM_COMMAND_ENABLE_LOOP, + FTDM_COMMAND_DISABLE_LOOP, FTDM_COMMAND_COUNT } ftdm_command_t; @@ -374,6 +376,7 @@ typedef enum { FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, + FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_INVALID } ftdm_channel_state_t; #define CHANNEL_STATE_STRINGS "DOWN", "HOLD", "SUSPENDED", "DIALTONE", "COLLECT", \