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
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 */
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:
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);
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;
/* 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:
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;
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;
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 */
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));
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);
spanpvt = val;
openr2_context_delete(spanpvt->r2context);
hashtable_destroy(spanpvt->r2calls);
+ ftdm_sched_destroy(&spanpvt->sched);
}
}
hashtable_destroy(g_mod_data_hash);