[AS_HELP_STRING([--with-pritap], [Install ftmod_pritap])],
[case "${withval}" in
no) enable_pritap="no" ;;
- *) enable_pritab="yes" ;;
+ *) enable_pritap="yes" ;;
esac],
[enable_pritap="no"]
)
}
return FTDM_SUCCESS;
}
+
+ case FTDM_SIGEVENT_RELEASED:
+ case FTDM_SIGEVENT_INDICATION_COMPLETED:
+ {
+ /* Swallow these events */
+ return FTDM_BREAK;
+ }
+ break;
default:
return FTDM_SUCCESS;
break;
}
}
break;
- case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
case FTDM_SIGEVENT_SIGSTATUS_CHANGED: { /* twiddle */ } break;
default:
}
}
break;
- case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
case FTDM_SIGEVENT_STOP:
{
}
break;
- case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
-
/* on DNIS received from the R2 forward side, return status == FTDM_BREAK to stop requesting DNIS */
case FTDM_SIGEVENT_COLLECTED_DIGIT:
{
}
break;
- case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
-
case FTDM_SIGEVENT_STOP:
case FTDM_SIGEVENT_RESTART:
{
ftdm_mutex_destroy(&ftdmchan->mutex);
ftdm_mutex_destroy(&ftdmchan->pre_buffer_mutex);
+ if (ftdmchan->state_completed_interrupt) {
+ ftdm_interrupt_destroy(&ftdmchan->state_completed_interrupt);
+ }
}
return FTDM_SUCCESS;
if (ftdm_test_flag(fchan, FTDM_CHANNEL_BLOCKING)) {
ftdm_clear_flag(fchan, FTDM_CHANNEL_BLOCKING);
- ftdm_interrupt_signal(fchan->state_change_notify);
+ ftdm_interrupt_signal(fchan->state_completed_interrupt);
}
return FTDM_SUCCESS;
return FTDM_FAIL;
}
- if (!ftdmchan->state_change_notify) {
- status = ftdm_interrupt_create(&ftdmchan->state_change_notify, FTDM_INVALID_SOCKET);
+ if (!ftdmchan->state_completed_interrupt) {
+ status = ftdm_interrupt_create(&ftdmchan->state_completed_interrupt, FTDM_INVALID_SOCKET);
if (status != FTDM_SUCCESS) {
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_CRIT,
"Failed to create state change interrupt when moving from %s to %s\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state));
goto done;
}
+ if (!waitrq) {
+ /* no waiting was requested */
+ goto done;
+ }
+
+ /* let's wait for the state change to be completed by the signaling stack */
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_BLOCKING);
ftdm_mutex_unlock(ftdmchan->mutex);
- status = ftdm_interrupt_wait(ftdmchan->state_change_notify, waitms);
+ status = ftdm_interrupt_wait(ftdmchan->state_completed_interrupt, waitms);
ftdm_mutex_lock(ftdmchan->mutex);
if (status != FTDM_SUCCESS) {
ftdm_log_chan_ex(ftdmchan, file, func, line,
- FTDM_LOG_LEVEL_WARNING, "state change from %s to %s was most likely not processed after aprox %dms\n",
+ FTDM_LOG_LEVEL_WARNING, "state change from %s to %s was most likely not completed after aprox %dms\n",
ftdm_channel_state2str(ftdmchan->last_state), ftdm_channel_state2str(state), DEFAULT_WAIT_TIME);
ok = 0;
goto done;
FT_DECLARE(ftdm_status_t) ftdm_channel_advance_states(ftdm_channel_t *fchan)
{
ftdm_channel_state_t state;
+
+ ftdm_assert_return(fchan->span->state_processor, FTDM_FAIL, "Cannot process states without a state processor!\n");
while (fchan->state_status == FTDM_STATE_STATUS_NEW) {
state = fchan->state;
if (done) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
- ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
ftdm_clear_flag_locked(ftdmchan->span, FTDM_SPAN_STATE_CHANGE);
+ ftdm_channel_complete_state(ftdmchan);
ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK] = 0;
}
}
break;
}
} else {
- ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
ftdm_clear_flag_locked(ftdmchan->span, FTDM_SPAN_STATE_CHANGE);
ftdm_channel_complete_state(ftdmchan);
indicate = 0;
!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) &&
ftdm_test_flag(analog_data, FTDM_ANALOG_ANSWER_POLARITY_REVERSE)) {
ftdm_polarity_t polarity = FTDM_POLARITY_REVERSE;
- if (ftdmchan->polarity != FTDM_POLARITY_FORWARD) {
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Polarity is already reversed on answer??\n");
- } else {
+ if (ftdmchan->polarity == FTDM_POLARITY_FORWARD) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Reversing polarity on answer\n");
ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_POLARITY, &polarity);
+ } else {
+ /* the polarity may be already reversed if this is the second time we
+ * answer (ie, due to 2 calls being on the same line) */
}
}
if (event->channel->state != FTDM_CHANNEL_STATE_DOWN) {
if (event->channel->state == FTDM_CHANNEL_STATE_HANGUP &&
ftdm_test_flag(event->channel, FTDM_CHANNEL_STATE_CHANGE)) {
- ftdm_clear_flag(event->channel, FTDM_CHANNEL_STATE_CHANGE);
/* we do not need to process HANGUP since the device also hangup already */
+ ftdm_channel_complete_state(event->channel);
}
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN);
}
{
if (event->channel->state == FTDM_CHANNEL_STATE_CALLWAITING) {
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_UP);
- ftdm_clear_flag(event->channel, FTDM_CHANNEL_STATE_CHANGE);
ftdm_clear_flag(event->channel->span, FTDM_SPAN_STATE_CHANGE);
+ ftdm_channel_complete_state(event->channel);
event->channel->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK] = 0;
}
break;
}
} else {
- ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
ftdm_clear_flag_locked(ftdmchan->span, FTDM_SPAN_STATE_CHANGE);
ftdm_channel_complete_state(ftdmchan);
indicate = 0;
* \param ftdmchan Channel to handle
* \note This function MUST be called with the channel locked
*/
-static __inline__ void state_advance(ftdm_channel_t *chan)
+static ftdm_status_t state_advance(ftdm_channel_t *chan)
{
ftdm_libpri_data_t *isdn_data = chan->span->signal_data;
q931_call *call = (q931_call *)chan->call_data;
sig.chan_id = ftdm_channel_get_id(chan);
sig.span_id = ftdm_channel_get_span_id(chan);
sig.channel = chan;
+
+ ftdm_channel_complete_state(chan);
switch (ftdm_channel_get_state(chan)) {
case FTDM_CHANNEL_STATE_DOWN:
ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan));
/* TODO: set hangup cause? */
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
- return;
+ return FTDM_SUCCESS;
}
ton = caller_data->dnis.type;
default:
break;
}
+ return FTDM_SUCCESS;
}
/**
for (j = 1; j <= ftdm_span_get_chan_count(span); j++) {
ftdm_channel_t *chan = ftdm_span_get_channel(span, j);
-
ftdm_channel_lock(chan);
- while (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) {
- ftdm_clear_flag(chan, FTDM_CHANNEL_STATE_CHANGE);
- state_advance(chan);
- ftdm_channel_complete_state(chan);
- }
+ ftdm_channel_advance_states(chan);
ftdm_channel_unlock(chan);
}
}
span->outgoing_call = isdn_outgoing_call;
span->state_map = &isdn_state_map;
+ span->state_processor = state_advance;
span->get_channel_sig_status = isdn_get_channel_sig_status;
span->get_span_sig_status = isdn_get_span_sig_status;
}
};
-static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
+static ftdm_status_t state_advance(ftdm_channel_t *ftdmchan)
{
ftdm_status_t status;
ftdm_sigmsg_t sig;
sig.span_id = ftdmchan->span_id;
sig.channel = ftdmchan;
+ ftdm_channel_complete_state(ftdmchan);
+
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_DOWN:
{
break;
}
- return;
+ return FTDM_SUCCESS;
}
static __inline__ void pritap_check_state(ftdm_span_t *span)
{
- if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) {
- uint32_t j;
- ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE);
- for(j = 1; j <= span->chan_count; j++) {
- if (ftdm_test_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE)) {
- ftdm_mutex_lock(span->channels[j]->mutex);
- ftdm_clear_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE);
- state_advance(span->channels[j]);
- ftdm_channel_complete_state(span->channels[j]);
- ftdm_mutex_unlock(span->channels[j]->mutex);
- }
- }
- }
+ if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) {
+ uint32_t j;
+ ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE);
+ for(j = 1; j <= span->chan_count; j++) {
+ ftdm_mutex_lock(span->channels[j]->mutex);
+ ftdm_channel_advance_states(span->channels[j]);
+ ftdm_mutex_unlock(span->channels[j]->mutex);
+ }
+ }
}
static int pri_io_read(struct pri *pri, void *buf, int buflen)
span->get_span_sig_status = pritap_get_span_sig_status;
span->state_map = &pritap_state_map;
+ span->state_processor = state_advance;
return FTDM_SUCCESS;
}
}
}
-static __inline__ void advance_chan_states(ftdm_channel_t *ftdmchan);
static __inline__ void stop_loop(ftdm_channel_t *ftdmchan);
/**
} else if (ftdmchan->state == FTDM_CHANNEL_STATE_IN_LOOP && retry) {
retry = 0;
stop_loop(ftdmchan);
- advance_chan_states(ftdmchan);
+ ftdm_channel_advance_states(ftdmchan);
goto tryagain;
} else {
ftdm_log(FTDM_LOG_ERROR, "s%dc%d: rejecting incoming call in channel state %s\n",
}
ftdm_mutex_lock(ftdmchan->mutex);
- advance_chan_states(ftdmchan);
+ ftdm_channel_advance_states(ftdmchan);
return ftdmchan;
}
}
if(ftdmchan != NULL) {
- advance_chan_states(ftdmchan);
+ ftdm_channel_advance_states(ftdmchan);
ftdm_mutex_unlock(ftdmchan->mutex);
}
- return 0;
+ return 0;
}
* \brief Handler for channel state change
* \param ftdmchan Channel to handle
*/
-static __inline__ ftdm_status_t state_advance(ftdm_channel_t *ftdmchan)
+static ftdm_status_t state_advance(ftdm_channel_t *ftdmchan)
{
ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data;
sangomabc_connection_t *mcon = &sangoma_boost_data->mcon;
ftdm_status_t status;
- if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
- ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
- } else {
- return FTDM_SUCCESS;
- }
-
ftdm_assert_return(ftdmchan->last_state != ftdmchan->state, FTDM_FAIL, "Channel state already processed\n");
ftdm_log(FTDM_LOG_DEBUG, "%d:%d PROCESSING STATE [%s]\n", ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state));
sig.span_id = ftdmchan->span_id;
sig.channel = ftdmchan;
+ ftdm_channel_complete_state(ftdmchan);
+
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_DOWN:
{
default:
break;
}
- ftdm_channel_complete_state(ftdmchan);
return FTDM_SUCCESS;
}
-static __inline__ void advance_chan_states(ftdm_channel_t *ftdmchan)
-{
- while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
- state_advance(ftdmchan);
- }
-}
-
/**
* \brief Initialises outgoing requests array
*/
static __inline__ void init_outgoing_array(void)
{
memset(&OUTBOUND_REQUESTS, 0, sizeof(OUTBOUND_REQUESTS));
-
}
/**
if (susp && span->channels[j]->state != FTDM_CHANNEL_STATE_DOWN) {
ftdm_set_state(span->channels[j], FTDM_CHANNEL_STATE_RESTART);
}
- state_advance(span->channels[j]);
+ ftdm_channel_advance_states(span->channels[j]);
ftdm_mutex_unlock(span->channels[j]->mutex);
}
}
* but without taking the chan out of the queue, so check th
* flag before advancing the state */
ftdm_mutex_lock(ftdmchan->mutex);
- state_advance(ftdmchan);
+ ftdm_channel_advance_states(ftdmchan);
ftdm_mutex_unlock(ftdmchan->mutex);
}
}
span->get_span_sig_status = sangoma_boost_get_span_sig_status;
span->set_span_sig_status = sangoma_boost_set_span_sig_status;
span->state_map = &boost_state_map;
+ span->state_processor = state_advance;
sangoma_boost_data->mcon.debuglevel = FTDM_LOG_LEVEL_DEBUG;
sangoma_boost_data->pcon.debuglevel = FTDM_LOG_LEVEL_DEBUG;
ftdm_clear_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID);
FTDM_COMMAND_GET_LINK_STATUS,
FTDM_COMMAND_ENABLE_LOOP,
FTDM_COMMAND_DISABLE_LOOP,
- FTDM_COMMAND_COUNT,
FTDM_COMMAND_SET_RX_QUEUE_SIZE,
FTDM_COMMAND_SET_TX_QUEUE_SIZE,
FTDM_COMMAND_SET_POLARITY,
+ FTDM_COMMAND_COUNT,
} ftdm_command_t;
typedef enum {
ftdm_dtmf_debug_t dtmfdbg;
ftdm_io_dump_t rxdump;
ftdm_io_dump_t txdump;
- ftdm_interrupt_t *state_change_notify; /*!< Notify when a state change is terminated */
+ ftdm_interrupt_t *state_completed_interrupt; /*!< Notify when a state change is completed */
int32_t txdrops;
int32_t rxdrops;
};