Fix for not handling a call state

Fix for MSN on BRI
This commit is contained in:
David Yat Sin 2010-09-30 11:41:47 -04:00
parent 6e14d6f5b2
commit c91d81a483
6 changed files with 83 additions and 19 deletions

View File

@ -726,7 +726,7 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_span_sig_status)
} }
static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span) static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
{ {
ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id); ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id);
if (sng_isdn_stack_start(span) != FTDM_SUCCESS) { if (sng_isdn_stack_start(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name); ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name);
@ -747,9 +747,11 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
} }
static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span) static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span)
{ {
ftdm_iterator_t *chaniter = NULL; ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL; ftdm_iterator_t *curr = NULL;
unsigned i;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
ftdm_log(FTDM_LOG_INFO, "Stopping span %s\n", span->name); ftdm_log(FTDM_LOG_INFO, "Stopping span %s\n", span->name);
/* throw the STOP_THREAD flag to signal monitor thread stop */ /* throw the STOP_THREAD flag to signal monitor thread stop */
@ -772,8 +774,13 @@ static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span)
} }
ftdm_iterator_free(chaniter); ftdm_iterator_free(chaniter);
ftdm_sched_destroy(&((sngisdn_span_data_t*)span->signal_data)->sched); ftdm_sched_destroy(&signal_data->sched);
ftdm_queue_destroy(&((sngisdn_span_data_t*)span->signal_data)->event_queue); ftdm_queue_destroy(&signal_data->event_queue);
for (i = 0 ; i < signal_data->num_local_numbers ; i++) {
if (signal_data->local_numbers[i] != NULL) {
ftdm_safe_free(signal_data->local_numbers[i]);
}
}
ftdm_safe_free(span->signal_data); ftdm_safe_free(span->signal_data);
ftdm_log(FTDM_LOG_DEBUG, "Finished stopping span %s\n", span->name); ftdm_log(FTDM_LOG_DEBUG, "Finished stopping span %s\n", span->name);

View File

@ -55,6 +55,7 @@
#define NUM_BRI_CHANNELS_PER_SPAN 2 #define NUM_BRI_CHANNELS_PER_SPAN 2
#define SNGISDN_EVENT_QUEUE_SIZE 100 #define SNGISDN_EVENT_QUEUE_SIZE 100
#define SNGISDN_EVENT_POLL_RATE 100 #define SNGISDN_EVENT_POLL_RATE 100
#define SNGISDN_NUM_LOCAL_NUMBERS 8
/* TODO: rename all *_cc_* to *_an_* */ /* TODO: rename all *_cc_* to *_an_* */
@ -161,7 +162,7 @@ typedef struct sngisdn_chan_data {
/* Span specific data */ /* Span specific data */
typedef struct sngisdn_span_data { typedef struct sngisdn_span_data {
ftdm_span_t *ftdm_span; ftdm_span_t *ftdm_span;
uint8_t link_id; uint8_t link_id;
uint8_t switchtype; uint8_t switchtype;
uint8_t signalling; /* SNGISDN_SIGNALING_CPE or SNGISDN_SIGNALING_NET */ uint8_t signalling; /* SNGISDN_SIGNALING_CPE or SNGISDN_SIGNALING_NET */
@ -175,7 +176,9 @@ typedef struct sngisdn_span_data {
uint8_t setup_arb; uint8_t setup_arb;
uint8_t facility; uint8_t facility;
int8_t facility_timeout; int8_t facility_timeout;
ftdm_sched_t *sched; uint8_t num_local_numbers;
char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
ftdm_sched_t *sched;
ftdm_queue_t *event_queue; ftdm_queue_t *event_queue;
} sngisdn_span_data_t; } sngisdn_span_data_t;

View File

@ -36,9 +36,23 @@
ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span); ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span);
ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span); ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span);
ftdm_status_t add_local_number(const char* val, ftdm_span_t *span);
extern ftdm_sngisdn_data_t g_sngisdn_data; extern ftdm_sngisdn_data_t g_sngisdn_data;
ftdm_status_t add_local_number(const char* val, ftdm_span_t *span)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
if (signal_data->num_local_numbers >= SNGISDN_NUM_LOCAL_NUMBERS) {
ftdm_log(FTDM_LOG_ERROR, "%s: Maximum number of local-numbers exceeded (max:%d)\n", span->name, SNGISDN_NUM_LOCAL_NUMBERS);
return FTDM_FAIL;
}
signal_data->local_numbers[signal_data->num_local_numbers++] = ftdm_strdup(val);
return FTDM_SUCCESS;
}
ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span) ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
{ {
unsigned i; unsigned i;
@ -253,6 +267,10 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
ftdm_span_set_bearer_capability(val, &span->default_caller_data.bearer_capability); ftdm_span_set_bearer_capability(val, &span->default_caller_data.bearer_capability);
} else if (!strcasecmp(var, "outbound-bearer_layer1")) { } else if (!strcasecmp(var, "outbound-bearer_layer1")) {
ftdm_span_set_bearer_layer1(val, &span->default_caller_data.bearer_layer1); ftdm_span_set_bearer_layer1(val, &span->default_caller_data.bearer_layer1);
} else if (!strcasecmp(var, "local-number")) {
if (add_local_number(val, span) != FTDM_SUCCESS) {
return FTDM_FAIL;
}
} else if (!strcasecmp(var, "facility-timeout")) { } else if (!strcasecmp(var, "facility-timeout")) {
signal_data->facility_timeout = atoi(val); signal_data->facility_timeout = atoi(val);
if (signal_data->facility_timeout < 0) { if (signal_data->facility_timeout < 0) {

View File

@ -43,7 +43,7 @@ extern ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Displ
void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
unsigned i;
int16_t suId = sngisdn_event->suId; int16_t suId = sngisdn_event->suId;
uint32_t suInstId = sngisdn_event->suInstId; uint32_t suInstId = sngisdn_event->suInstId;
uint32_t spInstId = sngisdn_event->spInstId; uint32_t spInstId = sngisdn_event->spInstId;
@ -57,7 +57,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
switch (ftdmchan->state) { switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_DOWN: /* Proper state to receive a SETUP */ case FTDM_CHANNEL_STATE_DOWN: /* Proper state to receive a SETUP */
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE) || if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE) ||
@ -80,11 +80,35 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
sngisdn_info->suInstId = get_unique_suInstId(suId); sngisdn_info->suInstId = get_unique_suInstId(suId);
sngisdn_info->spInstId = spInstId; sngisdn_info->spInstId = spInstId;
if (conEvnt->cdPtyNmb.eh.pres && signal_data->num_local_numbers) {
uint8_t local_number_matched = 0;
for (i = 0 ; i < signal_data->num_local_numbers ; i++) {
if (!strcmp(signal_data->local_numbers[i], (char*)conEvnt->cdPtyNmb.nmbDigits.val)) {
local_number_matched++;
break;
}
}
if (!local_number_matched) {
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SETUP, but local-number %s does not match - ignoring\n", conEvnt->cdPtyNmb.nmbDigits.val);
/* Special case to tell the stack to clear all internal resources about this call. We will no receive any event for this call after sending disconnect request */
ftdmchan->caller_data.hangup_cause = IN_CCNORTTODEST;
ftdm_sched_timer(signal_data->sched, "delayed_disconnect", 1, sngisdn_delayed_disconnect, (void*) sngisdn_info, NULL);
return;
}
}
/* If this is a glared call that was previously saved, we moved /* If this is a glared call that was previously saved, we moved
all the info to the current call, so clear the glared saved data */ all the info to the current call, so clear the glared saved data */
if (sngisdn_info->glare.spInstId == spInstId) { if (sngisdn_info->glare.spInstId == spInstId) {
clear_call_glare_data(sngisdn_info); clear_call_glare_data(sngisdn_info);
} }
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
sngisdn_info->ces = ces;
}
}
ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info; g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
@ -92,11 +116,6 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND); ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND);
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
signal_data->signalling == SNGISDN_SIGNALING_NET) {
sngisdn_info->ces = ces;
}
/* try to open the channel */ /* try to open the channel */
if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to open channel"); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to open channel");
@ -122,14 +141,13 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
ftdmchan->caller_data.bearer_layer1 = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].usrInfoLyr1Prot.val); ftdmchan->caller_data.bearer_layer1 = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].usrInfoLyr1Prot.val);
ftdmchan->caller_data.bearer_capability = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].infoTranCap.val); ftdmchan->caller_data.bearer_capability = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].infoTranCap.val);
} }
if (signal_data->switchtype == SNGISDN_SWITCH_NI2) { if (signal_data->switchtype == SNGISDN_SWITCH_NI2) {
if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) { if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) {
if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) { if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) {
snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]); snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]);
} }
} }
if (signal_data->facility == SNGISDN_OPT_TRUE && conEvnt->facilityStr.eh.pres) { if (signal_data->facility == SNGISDN_OPT_TRUE && conEvnt->facilityStr.eh.pres) {
/* Verify whether the Caller Name will come in a subsequent FACILITY message */ /* Verify whether the Caller Name will come in a subsequent FACILITY message */
@ -260,6 +278,10 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_DIALING: case FTDM_CHANNEL_STATE_DIALING:
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
break; break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
case FTDM_CHANNEL_STATE_HANGUP:
/* Race condition, we just hung up the call - ignore this message */
break;
default: default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state)); ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
@ -274,7 +296,7 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
/* do nothing */ /* do nothing */
break; break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* We just hung up an incoming call right after we sent a CONNECT so ignore this message */ /* Race condition, We just hung up an incoming call right after we sent a CONNECT - ignore this message */
break; break;
default: default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state)); ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
@ -923,6 +945,16 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
break; break;
} }
break; break;
case 12: /* We received a disconnect indication */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_TERMINATING:
/* We are already waiting for user app to handle the disconnect, do nothing */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
}
break;
case 22: case 22:
switch (ftdmchan->state) { switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_UP: case FTDM_CHANNEL_STATE_UP:

View File

@ -706,7 +706,7 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
ftdm_span_t *ftdmspan; ftdm_span_t *ftdmspan;
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[status->t.usta.suId]; sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[status->t.usta.suId];
if (!signal_data) { if (!signal_data) {
ftdm_log(FTDM_LOG_INFO, "Received q921 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.suId); ftdm_log(FTDM_LOG_INFO, "Received q931 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.suId);
return; return;
} }
ftdmspan = signal_data->ftdm_span; ftdmspan = signal_data->ftdm_span;

View File

@ -424,11 +424,15 @@ void sngisdn_delayed_disconnect(void* p_sngisdn_info)
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
ftdm_mutex_lock(ftdmchan->mutex); ftdm_mutex_lock(ftdmchan->mutex);
if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) { if (ftdmchan->caller_data.hangup_cause == IN_CCNORTTODEST || ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n",
signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId); signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId);
sngisdn_snd_disconnect(ftdmchan); sngisdn_snd_disconnect(ftdmchan);
if (ftdmchan->caller_data.hangup_cause == IN_CCNORTTODEST) {
ftdm_channel_t *close_chan = ftdmchan;
ftdm_channel_close(&close_chan);
}
} }
ftdm_mutex_unlock(ftdmchan->mutex); ftdm_mutex_unlock(ftdmchan->mutex);