void sngisdn_set_span_sig_status(ftdm_span_t *span, ftdm_signaling_status_t status) { ftdm_iterator_t *chaniter = NULL; ftdm_iterator_t *curr = NULL; chaniter = ftdm_span_get_chan_iterator(span, NULL); for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { sngisdn_set_chan_sig_status(((ftdm_channel_t*)ftdm_iterator_current(curr)), status); } ftdm_iterator_free(chaniter); return; }
ftdm_status_t sngisdn_set_span_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail) { if (FTDM_SPAN_IS_BRI(span)) { ftdm_iterator_t *chaniter = NULL; ftdm_iterator_t *curr = NULL; chaniter = ftdm_span_get_chan_iterator(span, NULL); for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { ftdm_log_chan(((ftdm_channel_t*)ftdm_iterator_current(curr)), FTDM_LOG_DEBUG, "Setting availability rate to:%d\n", avail); sngisdn_set_chan_avail_rate(((ftdm_channel_t*)ftdm_iterator_current(curr)), avail); } ftdm_iterator_free(chaniter); } return FTDM_SUCCESS; }
static ftdm_status_t sngisdn_map_call(sngisdn_span_data_t *signal_data, sngisdn_frame_info_t frame_info, ftdm_channel_t **found) { sngisdn_chan_data_t *sngisdn_info; ftdm_channel_t *ftdmchan = NULL; ftdm_iterator_t *chaniter = NULL; ftdm_iterator_t *curr = NULL; ftdm_status_t status = FTDM_FAIL; uint8_t outbound_call = 0; if ((!frame_info.call_ref_flag && frame_info.dir == FTDM_TRACE_DIR_OUTGOING) || (frame_info.call_ref_flag && frame_info.dir == FTDM_TRACE_DIR_INCOMING)) { /* If this is an outgoing frame and this frame was sent by the originating side of the call (frame_info.call_ref_flag == 0), then this is an outbound call */ outbound_call = 1; } else { outbound_call = 0; } switch (frame_info.msgtype) { case PROT_Q931_MSGTYPE_SETUP: /* We initiated this outgoing call try to match the call reference with our internal call-id*/ if (!frame_info.bchan_no) { /* We were not able to determine the bchannel on this call, so we will not be able to match it anyway */ status = FTDM_FAIL; } chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL); for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { ftdmchan = (ftdm_channel_t*)(ftdm_iterator_current(curr)); ftdm_channel_lock(ftdmchan); if (outbound_call) { sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data; if (sngisdn_info && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { if (ftdmchan->caller_data.call_id && ftdmchan->physical_chan_id == frame_info.bchan_no) { sngisdn_info->call_ref = frame_info.call_ref; *found = ftdmchan; status = FTDM_SUCCESS; } } } else { if (ftdmchan->physical_chan_id == frame_info.bchan_no) { *found = ftdmchan; status = FTDM_SUCCESS; } } ftdm_channel_unlock(ftdmchan); } ftdm_iterator_free(chaniter); break; case PROT_Q931_MSGTYPE_ALERTING: case PROT_Q931_MSGTYPE_PROCEEDING: case PROT_Q931_MSGTYPE_PROGRESS: case PROT_Q931_MSGTYPE_CONNECT: case PROT_Q931_MSGTYPE_SETUP_ACK: case PROT_Q931_MSGTYPE_CONNECT_ACK: case PROT_Q931_MSGTYPE_USER_INFO: case PROT_Q931_MSGTYPE_DISCONNECT: case PROT_Q931_MSGTYPE_RELEASE: case PROT_Q931_MSGTYPE_RELEASE_ACK: case PROT_Q931_MSGTYPE_RELEASE_COMPLETE: case PROT_Q931_MSGTYPE_FACILITY: case PROT_Q931_MSGTYPE_NOTIFY: case PROT_Q931_MSGTYPE_STATUS_ENQUIRY: case PROT_Q931_MSGTYPE_INFORMATION: case PROT_Q931_MSGTYPE_STATUS: /* Look for an outbound call on that span and and try to match the call-id */ chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL); for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { ftdmchan = (ftdm_channel_t*)(ftdm_iterator_current(curr)); ftdm_channel_lock(ftdmchan); sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data; if (outbound_call) { if (sngisdn_info && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { if (sngisdn_info->call_ref == frame_info.call_ref) { *found = ftdmchan; status = FTDM_SUCCESS; } } } else { if (sngisdn_info && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { if (sngisdn_info->call_ref && sngisdn_info->call_ref == frame_info.call_ref) { *found = ftdmchan; status = FTDM_SUCCESS; } } } ftdm_channel_unlock(ftdmchan); } ftdm_iterator_free(chaniter); break; default: /* This frame is not call specific, ignore */ break; } if (status == FTDM_SUCCESS) { ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Mapped %s with Call Ref:%04x to call-id:%d\n", get_code_2_str(frame_info.msgtype, dcodQ931MsgTypeTable), frame_info.call_ref, (*found)->caller_data.call_id); } else { /* We could not map this frame to a call-id */ ftdm_log(FTDM_LOG_DEBUG, "Failed to map %s with Call Ref:%04x to local call\n", get_code_2_str(frame_info.msgtype, dcodQ931MsgTypeTable), frame_info.call_ref); } return status; }
static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling) { wat_span_config_t span_config; ftdm_gsm_span_data_t *gsm_data = NULL; ftdm_iterator_t *chaniter = NULL; ftdm_iterator_t *citer = NULL; ftdm_channel_t *ftdmchan = NULL; ftdm_channel_t *dchan = NULL; ftdm_channel_t *bchan = NULL; unsigned paramindex = 0; const char *var = NULL; const char *val = NULL; /* libwat is smart enough to set good default values for the timers if they are set to 0 */ memset(&span_config, 0, sizeof(span_config)); /* set some span defaults */ span_config.moduletype = WAT_MODULE_TELIT; if (FTDM_SUCCESS != init_wat_lib()) { return FTDM_FAIL; } if (!sig_cb) { ftdm_log(FTDM_LOG_ERROR, "No signaling callback provided\n"); return FTDM_FAIL; } if (span->signal_type) { ftdm_log(FTDM_LOG_ERROR, "Span %s is already configured for another signaling\n", span->name); return FTDM_FAIL; } /* verify the span has one d-channel */ chaniter = ftdm_span_get_chan_iterator(span, NULL); if (!chaniter) { ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); return FTDM_FAIL; } citer = ftdm_span_get_chan_iterator(span, chaniter); for ( ; citer; citer = ftdm_iterator_next(citer)) { ftdmchan = ftdm_iterator_current(citer); if ((NULL == dchan) && FTDM_IS_DCHAN(ftdmchan)) { dchan = ftdmchan; } if ((NULL == bchan) && FTDM_IS_VOICE_CHANNEL(ftdmchan)) { bchan = ftdmchan; } } ftdm_iterator_free(chaniter); if (!dchan) { ftdm_log(FTDM_LOG_CRIT, "Could not find a d-channel for GSM span %s!\n", span->name); return FTDM_FAIL; } if (!bchan) { ftdm_log(FTDM_LOG_CRIT, "Could not find a b-channel for GSM span %s!\n", span->name); return FTDM_FAIL; } gsm_data = ftdm_calloc(1, sizeof(*gsm_data)); if (!gsm_data) { return FTDM_FAIL; } gsm_data->dchan = dchan; gsm_data->bchan = bchan; //sprintf(gsm_data->dchan->chan_name, "%s\t\n", "GSM dchan"); //sprintf(gsm_data->bchan->chan_name, "%s\r\n", "GSM bchan"); for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) { var = ftdm_parameters[paramindex].var; val = ftdm_parameters[paramindex].val; if (!ftdm_strlen_zero_buf(val)) { ftdm_log(FTDM_LOG_WARNING, "Ignoring empty GSM parameter %s for span %s\n", var, span->name); continue; } ftdm_log(FTDM_LOG_DEBUG, "Reading GSM parameter %s=%s for span %s\n", var, val, span->name); if (!strcasecmp(var, "moduletype")) { span_config.moduletype = wat_str2wat_moduletype(val); if (span_config.moduletype == WAT_MODULE_INVALID) { ftdm_log(FTDM_LOG_DEBUG, "Unknown GSM module type %s for span %s\n", val, span->name); continue; } ftdm_log(FTDM_LOG_DEBUG, "Configuring GSM span %s with moduletype %s\n", span->name, val); } else { ftdm_log(FTDM_LOG_ERROR, "Ignoring unknown GSM parameter '%s'", var); } } /* Bind function pointers for control operations */ span->start = ftdm_gsm_start; span->stop = ftdm_gsm_stop; span->sig_read = NULL; span->sig_write = NULL; span->signal_cb = sig_cb; span->signal_type = FTDM_SIGTYPE_GSM; span->signal_data = gsm_data; /* Gideon, plz fill me with gsm span specific data (you allocate and free) */ span->outgoing_call = gsm_outgoing_call; span->get_span_sig_status = ftdm_gsm_get_span_sig_status; span->set_span_sig_status = ftdm_gsm_set_span_sig_status; span->get_channel_sig_status = ftdm_gsm_get_channel_sig_status; span->set_channel_sig_status = ftdm_gsm_set_channel_sig_status; //printf("\r\nspan->state_map = &gsm_state_map;\r\n"); span->state_map = &gsm_state_map; span->state_processor = ftdm_gsm_state_advance; /* use signals queue */ ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE); ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE); /* we can skip states (going straight from RING to UP) */ ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES); gsm_data->span = span; #if 0 /* setup the scheduler (create if needed) */ 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; #endif fprintf(stdout, "Configuring wat span %d %s \r\n", span->span_id, span->name); if (wat_span_config(span->span_id, &span_config)) { ftdm_log(FTDM_LOG_ERROR, "Failed to configure span %s for GSM signaling!!\n", span->name); return FTDM_FAIL; } { int codec = FTDM_CODEC_SLIN; int interval = 20; ftdm_channel_command(gsm_data->bchan, FTDM_COMMAND_SET_NATIVE_CODEC, &codec); ftdm_channel_command(gsm_data->bchan, FTDM_COMMAND_SET_CODEC, &codec); ftdm_channel_command(gsm_data->bchan, FTDM_COMMAND_SET_INTERVAL, &interval); } return FTDM_SUCCESS; }
static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span) { unsigned i; ftdm_iterator_t *chaniter = NULL; ftdm_iterator_t *curr = NULL; //sngisdn_dchan_data_t *dchan_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; switch(span->trunk_type) { case FTDM_TRUNK_T1: if (!strcasecmp(switch_name, "ni2") || !strcasecmp(switch_name, "national")) { signal_data->switchtype = SNGISDN_SWITCH_NI2; } else if (!strcasecmp(switch_name, "5ess")) { signal_data->switchtype = SNGISDN_SWITCH_5ESS; } else if (!strcasecmp(switch_name, "4ess")) { signal_data->switchtype = SNGISDN_SWITCH_4ESS; } else if (!strcasecmp(switch_name, "dms100")) { signal_data->switchtype = SNGISDN_SWITCH_DMS100; } else if (!strcasecmp(switch_name, "qsig")) { signal_data->switchtype = SNGISDN_SWITCH_QSIG; } else { ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported switchtype %s for trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type)); return FTDM_FAIL; } break; case FTDM_TRUNK_E1: if (!strcasecmp(switch_name, "euroisdn") || !strcasecmp(switch_name, "etsi")) { signal_data->switchtype = SNGISDN_SWITCH_EUROISDN; } else if (!strcasecmp(switch_name, "qsig")) { signal_data->switchtype = SNGISDN_SWITCH_QSIG; } else { ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported switchtype %s for trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type)); return FTDM_FAIL; } break; case FTDM_TRUNK_BRI: case FTDM_TRUNK_BRI_PTMP: if (!strcasecmp(switch_name, "euroisdn") || !strcasecmp(switch_name, "etsi")) { signal_data->switchtype = SNGISDN_SWITCH_EUROISDN; } else if (!strcasecmp(switch_name, "insnet") || !strcasecmp(switch_name, "ntt")) { signal_data->switchtype = SNGISDN_SWITCH_INSNET; } else { ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported switchtype %s for trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type)); return FTDM_FAIL; } ftdm_set_flag(span, FTDM_SPAN_USE_AV_RATE); ftdm_set_flag(span, FTDM_SPAN_PWR_SAVING); /* can be > 1 for some BRI variants */ break; default: ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported trunktype:%s\n", span->name, ftdm_trunk_type2str(span->trunk_type)); return FTDM_FAIL; } /* see if we have profile with this switch_type already */ for (i = 1; i <= g_sngisdn_data.num_cc; i++) { if (g_sngisdn_data.ccs[i].switchtype == signal_data->switchtype && g_sngisdn_data.ccs[i].trunktype == span->trunk_type) { break; } } /* need to create a new switch_type */ if (i > g_sngisdn_data.num_cc) { g_sngisdn_data.num_cc++; g_sngisdn_data.ccs[i].switchtype = signal_data->switchtype; g_sngisdn_data.ccs[i].trunktype = span->trunk_type; ftdm_log(FTDM_LOG_DEBUG, "%s: New switchtype:%s cc_id:%u\n", span->name, switch_name, i); } /* add this span to its ent_cc */ signal_data->cc_id = i; g_sngisdn_data.spans[signal_data->link_id] = signal_data; ftdm_log(FTDM_LOG_DEBUG, "%s: cc_id:%d link_id:%d\n", span->name, signal_data->cc_id, signal_data->link_id); chaniter = ftdm_span_get_chan_iterator(span, NULL); for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { int32_t chan_id; ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr); if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) { /* set the d-channel */ signal_data->dchan = ftdmchan; } else { /* Add the channels to the span */ chan_id = ftdmchan->physical_chan_id; signal_data->channels[chan_id] = (sngisdn_chan_data_t*)ftdmchan->call_data; signal_data->num_chans++; } } ftdm_iterator_free(chaniter); return FTDM_SUCCESS; }