}
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);
if (sng_isdn_stack_start(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name);
}
static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span)
-{
+{
ftdm_iterator_t *chaniter = 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);
/* throw the STOP_THREAD flag to signal monitor thread stop */
}
ftdm_iterator_free(chaniter);
- ftdm_sched_destroy(&((sngisdn_span_data_t*)span->signal_data)->sched);
- ftdm_queue_destroy(&((sngisdn_span_data_t*)span->signal_data)->event_queue);
+ ftdm_sched_destroy(&signal_data->sched);
+ 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_log(FTDM_LOG_DEBUG, "Finished stopping span %s\n", span->name);
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 add_local_number(const char* val, ftdm_span_t *span);
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)
{
unsigned i;
ftdm_span_set_bearer_capability(val, &span->default_caller_data.bearer_capability);
} else if (!strcasecmp(var, "outbound-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")) {
signal_data->facility_timeout = atoi(val);
if (signal_data->facility_timeout < 0) {
void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-
+ unsigned i;
int16_t suId = sngisdn_event->suId;
uint32_t suInstId = sngisdn_event->suInstId;
uint32_t spInstId = sngisdn_event->spInstId;
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);
-
+
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_DOWN: /* Proper state to receive a SETUP */
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE) ||
sngisdn_info->suInstId = get_unique_suInstId(suId);
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
all the info to the current call, so clear the glared saved data */
if (sngisdn_info->glare.spInstId == spInstId) {
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);
g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
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 */
if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to open channel");
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);
}
-
+
if (signal_data->switchtype == SNGISDN_SWITCH_NI2) {
if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) {
if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) {
snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]);
}
}
-
if (signal_data->facility == SNGISDN_OPT_TRUE && conEvnt->facilityStr.eh.pres) {
/* Verify whether the Caller Name will come in a subsequent FACILITY message */
case FTDM_CHANNEL_STATE_DIALING:
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
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:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
/* do nothing */
break;
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;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
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:
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_UP: