From e6250bcb9493aae8a3e8afdf1502c8417b110072 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 8 Dec 2010 13:15:26 -0500 Subject: [PATCH] freetdm: ftmod_r2 - Add protocol error recovery timer --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 40 ++++++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index fa0479d48b..166a914100 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -138,6 +138,8 @@ typedef struct ftdm_r2_data_s { uint32_t monitor_thread_id; /* Logging directory */ char logdir[512]; + /* scheduling context */ + ftdm_sched_t *sched; } ftdm_r2_data_t; /* one element per span will be stored in g_mod_data_hash global var to keep track of them @@ -145,6 +147,7 @@ typedef struct ftdm_r2_data_s { typedef struct ftdm_r2_span_pvt_s { openr2_context_t *r2context; /* r2 context allocated for this span */ ftdm_hash_t *r2calls; /* hash table of allocated call data per channel for this span */ + ftdm_sched_t *sched; /* schedule for the span */ } ftdm_r2_span_pvt_t; /* span monitor thread */ @@ -312,6 +315,7 @@ static openr2_call_disconnect_cause_t ftdm_r2_ftdm_cause_to_openr2_cause(ftdm_ch case FTDM_CAUSE_NETWORK_OUT_OF_ORDER: case FTDM_CAUSE_SERVICE_UNAVAILABLE: + case FTDM_CAUSE_PROTOCOL_ERROR: return OR2_CAUSE_OUT_OF_ORDER; case FTDM_CAUSE_NO_ANSWER: @@ -644,6 +648,20 @@ static void ftdm_r2_on_os_error(openr2_chan_t *r2chan, int errorcode) ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "OS error: %s\n", strerror(errorcode)); } +static void ftdm_r2_recover_from_protocol_error(void *data) +{ + openr2_chan_t *r2chan = data; + ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); + ftdm_channel_lock(ftdmchan); + if (ftdmchan->state != FTDM_CHANNEL_STATE_HANGUP) { + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Recovering from protocol error but state is %s!\n", ftdm_channel_state2str(ftdmchan->state)); + goto done; + } + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); +done: + ftdm_channel_unlock(ftdmchan); +} + static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason) { ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); @@ -1115,6 +1133,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling) unsigned int i = 0; int conf_failure = 0; int intval = 0; + char schedname[255]; const char *var = NULL, *val = NULL; const char *log_level = "notice,warning,error"; /* default loglevel, if none is read from conf */ ftdm_r2_data_t *r2data = NULL; @@ -1374,6 +1393,11 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling) /* use signals queue */ ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE); + /* setup the scheduler */ + snprintf(schedname, sizeof(schedname), "ftmod_r2_%s", span->name); + ftdm_assert(ftdm_sched_create(&r2data->sched, schedname) == FTDM_SUCCESS, "Failed to create schedule!\n"); + spanpvt->sched = r2data->sched; + return FTDM_SUCCESS; fail: @@ -1396,6 +1420,7 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) ftdm_sigmsg_t sigev; int ret; openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan; + ftdm_r2_data_t *r2data = ftdmchan->span->signal_data; memset(&sigev, 0, sizeof(sigev)); sigev.chan_id = ftdmchan->chan_id; @@ -1526,7 +1551,9 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) openr2_chan_disconnect_call(r2chan, OR2_CAUSE_NORMAL_CLEARING); } else { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Clearing call due to protocol error\n"); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + /* do not set to down yet, give some time for recovery */ + ftdm_sched_timer(r2data->sched, "protocolerr_recover", 100, + ftdm_r2_recover_from_protocol_error, r2chan, NULL); } } break; @@ -1650,6 +1677,11 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) r2data->total_loops++; } + /* run any span timers */ + ftdm_sched_run(r2data->sched); + + /* deliver the actual channel events to the user now without any channel locking */ + ftdm_span_trigger_signals(span); #ifndef WIN32 /* figure out what event to poll each channel for. POLLPRI when the channel is down, * POLLPRI|POLLIN|POLLOUT otherwise */ @@ -1669,6 +1701,9 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) status = ftdm_span_poll_event(span, waitms, NULL); #endif + /* run any span timers */ + ftdm_sched_run(r2data->sched); + res = gettimeofday(&start, NULL); if (res) { ftdm_log(FTDM_LOG_CRIT, "Failure gettimeofday [%s]\n", strerror(errno)); @@ -1722,8 +1757,6 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) ftdm_mutex_unlock(ftdmchan->mutex); } - /* deliver the actual events to the user now without any channel locking */ - ftdm_span_trigger_signals(span); } chaniter = ftdm_span_get_chan_iterator(span, chaniter); @@ -2046,6 +2079,7 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_r2_destroy) spanpvt = val; openr2_context_delete(spanpvt->r2context); hashtable_destroy(spanpvt->r2calls); + ftdm_sched_destroy(&spanpvt->sched); } } hashtable_destroy(g_mod_data_hash);