freetdm: ftmod_r2 - Add protocol error recovery timer

This commit is contained in:
Moises Silva 2010-12-08 13:15:26 -05:00
parent de23c6d375
commit e6250bcb94

View file

@ -138,6 +138,8 @@ typedef struct ftdm_r2_data_s {
uint32_t monitor_thread_id; uint32_t monitor_thread_id;
/* Logging directory */ /* Logging directory */
char logdir[512]; char logdir[512];
/* scheduling context */
ftdm_sched_t *sched;
} ftdm_r2_data_t; } ftdm_r2_data_t;
/* one element per span will be stored in g_mod_data_hash global var to keep track of them /* 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 { typedef struct ftdm_r2_span_pvt_s {
openr2_context_t *r2context; /* r2 context allocated for this span */ 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_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; } ftdm_r2_span_pvt_t;
/* span monitor thread */ /* 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_NETWORK_OUT_OF_ORDER:
case FTDM_CAUSE_SERVICE_UNAVAILABLE: case FTDM_CAUSE_SERVICE_UNAVAILABLE:
case FTDM_CAUSE_PROTOCOL_ERROR:
return OR2_CAUSE_OUT_OF_ORDER; return OR2_CAUSE_OUT_OF_ORDER;
case FTDM_CAUSE_NO_ANSWER: 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)); 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) 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); 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; unsigned int i = 0;
int conf_failure = 0; int conf_failure = 0;
int intval = 0; int intval = 0;
char schedname[255];
const char *var = NULL, *val = NULL; const char *var = NULL, *val = NULL;
const char *log_level = "notice,warning,error"; /* default loglevel, if none is read from conf */ const char *log_level = "notice,warning,error"; /* default loglevel, if none is read from conf */
ftdm_r2_data_t *r2data = NULL; ftdm_r2_data_t *r2data = NULL;
@ -1374,6 +1393,11 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
/* use signals queue */ /* use signals queue */
ftdm_set_flag(span, FTDM_SPAN_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; return FTDM_SUCCESS;
fail: fail:
@ -1396,6 +1420,7 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
ftdm_sigmsg_t sigev; ftdm_sigmsg_t sigev;
int ret; int ret;
openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan; openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan;
ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
memset(&sigev, 0, sizeof(sigev)); memset(&sigev, 0, sizeof(sigev));
sigev.chan_id = ftdmchan->chan_id; 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); openr2_chan_disconnect_call(r2chan, OR2_CAUSE_NORMAL_CLEARING);
} else { } else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Clearing call due to protocol error\n"); 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; break;
@ -1650,6 +1677,11 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
r2data->total_loops++; 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 #ifndef WIN32
/* figure out what event to poll each channel for. POLLPRI when the channel is down, /* figure out what event to poll each channel for. POLLPRI when the channel is down,
* POLLPRI|POLLIN|POLLOUT otherwise */ * 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); status = ftdm_span_poll_event(span, waitms, NULL);
#endif #endif
/* run any span timers */
ftdm_sched_run(r2data->sched);
res = gettimeofday(&start, NULL); res = gettimeofday(&start, NULL);
if (res) { if (res) {
ftdm_log(FTDM_LOG_CRIT, "Failure gettimeofday [%s]\n", strerror(errno)); 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); 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); chaniter = ftdm_span_get_chan_iterator(span, chaniter);
@ -2046,6 +2079,7 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_r2_destroy)
spanpvt = val; spanpvt = val;
openr2_context_delete(spanpvt->r2context); openr2_context_delete(spanpvt->r2context);
hashtable_destroy(spanpvt->r2calls); hashtable_destroy(spanpvt->r2calls);
ftdm_sched_destroy(&spanpvt->sched);
} }
} }
hashtable_destroy(g_mod_data_hash); hashtable_destroy(g_mod_data_hash);