diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 4fda283aeb..aaddbf69f0 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -2923,102 +2923,49 @@ static switch_status_t load_config(void) if ((spans = switch_xml_child(cfg, "pri_spans"))) { for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) { - char *id = (char *) switch_xml_attr(myspan, "id"); char *name = (char *) switch_xml_attr(myspan, "name"); + ftdm_conf_parameter_t spanparameters[10]; ftdm_status_t zstatus = FTDM_FAIL; const char *context = "default"; const char *dialplan = "XML"; - //Q921NetUser_t mode = Q931_TE; - //Q931Dialect_t dialect = Q931_Dialect_National; - char *mode = NULL; - char *dialect = NULL; - uint32_t span_id = 0; + unsigned paramindex = 0; ftdm_span_t *span = NULL; - const char *tonegroup = NULL; - char *digit_timeout = NULL; - const char *opts = "none"; - uint32_t to = 0; - int q921loglevel = -1; - int q931loglevel = -1; - - // quick debug - //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ID: '%s', Name:'%s'\n",id,name); + uint32_t span_id = 0; - for (param = switch_xml_child(myspan, "param"); param; param = param->next) { + if (!name) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required attribute 'name'\n"); + continue; + } + + for (param = switch_xml_child(myspan, "param"); param && paramindex < 10; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); - if (!strcasecmp(var, "tonegroup")) { - tonegroup = val; - } else if (!strcasecmp(var, "mode")) { - mode = val; - } else if (!strcasecmp(var, "dialect")) { - dialect = val; - } else if (!strcasecmp(var, "q921loglevel")) { - if ((q921loglevel = switch_log_str2level(val)) == SWITCH_LOG_INVALID) { - q921loglevel = -1; - } - } else if (!strcasecmp(var, "q931loglevel")) { - if ((q931loglevel = switch_log_str2level(val)) == SWITCH_LOG_INVALID) { - q931loglevel = -1; - } - } else if (!strcasecmp(var, "context")) { + if (ftdm_array_len(spanparameters) == paramindex) { + ftdm_log(FTDM_LOG_ERROR, "Too many parameters for pri span '%s', ignoring everything after '%s'\n", name, var); + break; + } + + if (!strcasecmp(var, "context")) { context = val; - } else if (!strcasecmp(var, "opts")) { - opts = val; } else if (!strcasecmp(var, "dialplan")) { dialplan = val; - } else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "digit-timeout")) { - digit_timeout = val; - } - } - - if (!id && !name) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n"); - continue; - } - - if (name) { - zstatus = ftdm_span_find_by_name(name, &span); - } else { - if (switch_is_number(id)) { - span_id = atoi(id); - zstatus = ftdm_span_find(span_id, &span); - } - - if (zstatus != FTDM_SUCCESS) { - zstatus = ftdm_span_find_by_name(id, &span); + } else { + spanparameters[paramindex].var = var; + spanparameters[paramindex].val = val; + paramindex++; } } - if (digit_timeout) { - to = atoi(digit_timeout); - } - + zstatus = ftdm_span_find_by_name(name, &span); if (zstatus != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name)); + ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span %s\n", name); continue; } - if (!span_id) { - span_id = ftdm_span_get_id(span); - } - - if (!tonegroup) { - tonegroup = "us"; - } - - if (ftdm_configure_span(span, "isdn", on_clear_channel_signal, - "mode", mode, - "dialect", dialect, - "digit_timeout", &to, - "opts", opts, - "tonemap", tonegroup, - "q921loglevel", q921loglevel, - "q931loglevel", q931loglevel, - FTDM_TAG_END) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error starting FreeTDM span %d mode: %s dialect: %s error: %s\n", span_id, - mode, dialect, ftdm_span_get_last_error(span)); + span_id = ftdm_span_get_id(span); + if (ftdm_configure_span_signaling(span, "isdn", on_clear_channel_signal, spanparameters) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM span %s\n", name); continue; } diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c index 2b34552950..03c027e664 100644 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c @@ -54,6 +54,24 @@ #define DEFAULT_NATIONAL_PREFIX "0" #define DEFAULT_INTERNATIONAL_PREFIX "00" +static const char *ftdm_span_get_trunk_type_str(const ftdm_span_t *span) +{ + assert(span); + return ftdm_trunk_type2str(span->trunk_type); +} + +static int ftdm_channel_get_state(const ftdm_channel_t *chan) +{ + assert(chan); + return chan->state; +} + +static int ftdm_channel_get_last_state(const ftdm_channel_t *chan) +{ + assert(chan); + return chan->last_state; +} + /***************************************************************************************** * PCAP * Based on Helmut Kuper's () implementation, @@ -90,13 +108,8 @@ static ftdm_status_t isdn_pcap_open(struct ftdm_isdn_data *isdn, char *filename) { struct pcap_context *pcap = NULL; - if (!isdn) { + if (!isdn || ftdm_strlen_zero(filename)) return FTDM_FAIL; - } - - if (ftdm_strlen_zero(filename)) { - return FTDM_FAIL; - } pcap = malloc(sizeof(struct pcap_context)); if (!pcap) { @@ -116,23 +129,20 @@ static ftdm_status_t isdn_pcap_open(struct ftdm_isdn_data *isdn, char *filename) pcap->dump = pcap_dump_open(pcap->handle, pcap->filename); if (!pcap->dump) { - ftdm_log(FTDM_LOG_ERROR, "Failed to open capture file: %s\n", pcap_geterr(pcap->handle)); + ftdm_log(FTDM_LOG_ERROR, "Failed to open capture file: '%s'\n", pcap_geterr(pcap->handle)); goto error; } - ftdm_log(FTDM_LOG_INFO, "Capture file \"%s\" opened\n", pcap->filename); + ftdm_log(FTDM_LOG_INFO, "Capture file '%s' opened\n", pcap->filename); isdn->pcap = pcap; return FTDM_SUCCESS; - error: - if (pcap->handle) { + if (pcap->handle) pcap_close(pcap->handle); - } - if (pcap->filename) { + if (pcap->filename) free(pcap->filename); - } free(pcap); @@ -144,9 +154,9 @@ static ftdm_status_t isdn_pcap_close(struct ftdm_isdn_data *isdn) struct pcap_context *pcap = NULL; long size; - if (!isdn || !isdn->pcap) { + if (!isdn || !isdn->pcap) return FTDM_FAIL; - } + pcap = isdn->pcap; isdn->flags &= ~(FTDM_ISDN_CAPTURE | FTDM_ISDN_CAPTURE_L3ONLY); @@ -155,7 +165,7 @@ static ftdm_status_t isdn_pcap_close(struct ftdm_isdn_data *isdn) pcap_dump_flush(pcap->dump); size = pcap_dump_ftell(pcap->dump); - ftdm_log(FTDM_LOG_INFO, "File \"%s\" captured %ld bytes of data\n", pcap->filename, size); + ftdm_log(FTDM_LOG_INFO, "File '%s' captured %ld bytes of data\n", pcap->filename, size); pcap_dump_close(pcap->dump); pcap_close(pcap->handle); @@ -209,9 +219,8 @@ static ftdm_status_t isdn_pcap_write(struct ftdm_isdn_data *isdn, unsigned char int offset = sizeof(struct isdn_sll_hdr); int nbytes; - if (!isdn || !isdn->pcap || !buf || !len) { + if (!isdn || !isdn->pcap || !buf || !len) return FTDM_FAIL; - } pcap = isdn->pcap; @@ -431,7 +440,7 @@ static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request) isdn_data->outbound_crv[gen->CRV] = caller_data; //isdn_data->channels_local_crv[gen->CRV] = ftdmchan; - while(ftdm_running() && caller_data->call_state == FTDM_CALLER_STATE_DIALING) { + while (ftdm_running() && caller_data->call_state == FTDM_CALLER_STATE_DIALING) { ftdm_sleep(1); if (!--sanity) { @@ -446,8 +455,8 @@ static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request) int fail = 1; new_chan = NULL; - if (caller_data->chan_id < FTDM_MAX_CHANNELS_SPAN && caller_data->chan_id <= span->chan_count) { - new_chan = span->channels[caller_data->chan_id]; + if (caller_data->chan_id > 0 && caller_data->chan_id <= ftdm_span_get_chan_count(span)) { + new_chan = ftdm_span_get_channel(span, caller_data->chan_id); } if (new_chan && (status = ftdm_channel_open_chan(new_chan) == FTDM_SUCCESS)) { @@ -565,10 +574,8 @@ static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent * /* * Global event */ - ftdm_log(FTDM_LOG_DEBUG, "Received global event from Q.931\n"); - } - else { + } else { ftdm_channel_t *ftdmchan = NULL; ftdm_sigmsg_t sig; int call_crv = Q931CallGetCRV(call); @@ -711,9 +718,8 @@ static void __isdn_get_number(const char *digits, const int ton, char *buf, int { int offset = 0; - if (!digits || !buf || size <= 0) { + if (!digits || !buf || size <= 0) return; - } switch (ton) { case Q931_TON_NATIONAL: @@ -742,24 +748,23 @@ static void __isdn_get_number(const char *digits, const int ton, char *buf, int */ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic *msg, int mlen) { + Q931mes_Generic *gen = (Q931mes_Generic *) msg; ftdm_span_t *span = (ftdm_span_t *) pvt; ftdm_isdn_data_t *isdn_data = span->signal_data; - Q931mes_Generic *gen = (Q931mes_Generic *) msg; + ftdm_channel_t *ftdmchan = NULL; int chan_id = 0; int chan_hunt = 0; - ftdm_channel_t *ftdmchan = NULL; -// ftdm_caller_data_t *caller_data = NULL; if (Q931IsIEPresent(gen->ChanID)) { Q931ie_ChanID *chanid = Q931GetIEPtr(gen->ChanID, gen->buf); - if(chanid->IntType) + if (chanid->IntType) chan_id = chanid->ChanSlot; else chan_id = chanid->InfoChanSel; /* "any" channel specified */ - if(chanid->InfoChanSel == 3) { + if (chanid->InfoChanSel == 3) { chan_hunt++; } } else if (FTDM_SPAN_IS_NT(span)) { @@ -805,9 +810,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic case Q931mes_ALERTING: case Q931mes_PROGRESS: case Q931mes_CONNECT: - { - caller_data->call_state = FTDM_CALLER_STATE_SUCCESS; - } + caller_data->call_state = FTDM_CALLER_STATE_SUCCESS; break; default: caller_data->call_state = FTDM_CALLER_STATE_FAIL; @@ -824,8 +827,12 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic ftdmchan = isdn_data->channels_remote_crv[gen->CRV]; } - ftdm_log(FTDM_LOG_DEBUG, "ftdmchan %x (%d:%d) source isdn_data->channels_%s_crv[%#hx]\n", ftdmchan, ftdmchan ? ftdmchan->span_id : -1, ftdmchan ? ftdmchan->chan_id : -1, gen->CRVFlag ? "local" : "remote", gen->CRV); - + ftdm_log(FTDM_LOG_DEBUG, "ftdmchan %x (%d:%d) source isdn_data->channels_%s_crv[%#hx]\n", + ftdmchan, + ((ftdmchan) ? ftdm_channel_get_span_id(ftdmchan) : -1), + ((ftdmchan) ? ftdm_channel_get_id(ftdmchan) : -1), + ((gen->CRVFlag) ? "local" : "remote"), + gen->CRV); if (gen->ProtDisc == 3) { switch(gen->MesType) { @@ -837,7 +844,9 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic case 0: /* change status to "in service" */ { ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_SUSPENDED); - ftdm_log(FTDM_LOG_DEBUG, "Channel %d:%d in service\n", ftdmchan->span_id, ftdmchan->chan_id); + ftdm_log(FTDM_LOG_DEBUG, "Channel %d:%d in service\n", + ftdm_channel_get_span_id(ftdmchan), + ftdm_channel_get_id(ftdmchan)); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); } break; @@ -869,19 +878,20 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic case Q931mes_RESTART: { if (chan_id) { - ftdmchan = span->channels[chan_id]; + ftdmchan = ftdm_span_get_channel(span, chan_id); } if (ftdmchan) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); } else { uint32_t i; - for (i = 1; i < span->chan_count; i++) { + for (i = 1; i < ftdm_span_get_chan_count(span); i++) { /* Skip channels that are down and D-Channels (#OpenZAP-39) */ - if (span->channels[i]->state == FTDM_CHANNEL_STATE_DOWN || span->channels[i]->type == FTDM_CHAN_TYPE_DQ921) + if (ftdm_channel_get_state(span->channels[i]) == FTDM_CHANNEL_STATE_DOWN || + ftdm_channel_get_type(span->channels[i]) == FTDM_CHAN_TYPE_DQ921) continue; - ftdm_set_state_locked((span->channels[i]), FTDM_CHANNEL_STATE_RESTART); + ftdm_set_state_locked(span->channels[i], FTDM_CHANNEL_STATE_RESTART); } } } @@ -891,15 +901,17 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic { const char *what = gen->MesType == Q931mes_RELEASE ? "Release" : "Release Complete"; if (ftdmchan) { - if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING || ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP) { + if (ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_TERMINATING || + ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_HANGUP) + { if (gen->MesType == Q931mes_RELEASE) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); } else { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } } - else if((gen->MesType == Q931mes_RELEASE && ftdmchan->state <= FTDM_CHANNEL_STATE_UP) || - (gen->MesType == Q931mes_RELEASE_COMPLETE && ftdmchan->state == FTDM_CHANNEL_STATE_DIALING)) { + else if ((gen->MesType == Q931mes_RELEASE && ftdm_channel_get_state(ftdmchan) <= FTDM_CHANNEL_STATE_UP) || + (gen->MesType == Q931mes_RELEASE_COMPLETE && ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DIALING)) { /* * Don't keep inbound channels open if the remote side hangs up before we answered @@ -909,18 +921,20 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic ftdm_status_t status; memset(&sig, 0, sizeof(sig)); - sig.chan_id = ftdmchan->chan_id; - sig.span_id = ftdmchan->span_id; + sig.span_id = ftdm_channel_get_span_id(ftdmchan); + sig.chan_id = ftdm_channel_get_id(ftdmchan); sig.channel = ftdmchan; sig.channel->caller_data.hangup_cause = (cause) ? cause->Value : FTDM_CAUSE_NORMAL_UNSPECIFIED; sig.event_id = FTDM_SIGEVENT_STOP; status = isdn_data->sig_cb(&sig); - ftdm_log(FTDM_LOG_DEBUG, "Received %s in state %s, requested hangup for channel %d:%d\n", what, ftdm_channel_state2str(ftdmchan->state), ftdmchan->span_id, chan_id); - } - else { - ftdm_log(FTDM_LOG_DEBUG, "Ignoring %s on channel %d\n", what, chan_id); + ftdm_log(FTDM_LOG_DEBUG, "Received %s in state %s, requested hangup for channel %d:%d\n", what, + ftdm_channel_get_state_str(ftdmchan), + ftdm_channel_get_span_id(ftdmchan), + ftdm_channel_get_id(ftdmchan)); + } else { + ftdm_log(FTDM_LOG_DEBUG, "Ignoring %s on channel %d\n", what, ftdm_channel_get_id(ftdmchan)); } } else { ftdm_log(FTDM_LOG_CRIT, "Received %s with no matching channel %d\n", what, chan_id); @@ -977,18 +991,18 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic { Q931ie_CallingNum *callingnum = Q931GetIEPtr(gen->CallingNum, gen->buf); Q931ie_CalledNum *callednum = Q931GetIEPtr(gen->CalledNum, gen->buf); - int fail = 1; - int fail_cause = 0; - int overlap_dial = 0; uint32_t cplen = mlen; + int overlap_dial = 0; + int fail_cause = 0; + int fail = 1; - if(ftdmchan && ftdmchan == isdn_data->channels_remote_crv[gen->CRV]) { + if (ftdmchan && ftdmchan == isdn_data->channels_remote_crv[gen->CRV]) { ftdm_log(FTDM_LOG_INFO, "Duplicate SETUP message(?) for Channel %d:%d ~ %d:%d in state %s [ignoring]\n", - ftdmchan->span_id, - ftdmchan->chan_id, - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id, - ftdm_channel_state2str(ftdmchan->state)); + ftdm_channel_get_span_id(ftdmchan), + ftdm_channel_get_id(ftdmchan), + ftdm_channel_get_ph_span_id(ftdmchan), + ftdm_channel_get_ph_id(ftdmchan), + ftdm_channel_get_state_str(ftdmchan)); break; } @@ -1003,10 +1017,10 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic * In NT-mode with channel selection "any", * try to find a free channel */ - for (x = 1; x <= span->chan_count; x++) { - ftdm_channel_t *zc = span->channels[x]; + for (x = 1; x <= ftdm_span_get_chan_count(span); x++) { + ftdm_channel_t *zc = ftdm_span_get_channel(span, x); - if (!ftdm_test_flag(zc, FTDM_CHANNEL_INUSE) && zc->state == FTDM_CHANNEL_STATE_DOWN) { + if (!ftdm_test_flag(zc, FTDM_CHANNEL_INUSE) && ftdm_channel_get_state(zc) == FTDM_CHANNEL_STATE_DOWN) { ftdmchan = zc; break; } @@ -1027,8 +1041,8 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic * TODO: NT mode is abled to select a different channel if the one chosen * by the TE side is already in use */ - if (chan_id > 0 && chan_id < FTDM_MAX_CHANNELS_SPAN && chan_id <= span->chan_count) { - ftdmchan = span->channels[chan_id]; + if (chan_id > 0 && chan_id < FTDM_MAX_CHANNELS_SPAN && chan_id <= ftdm_span_get_chan_count(span)) { + ftdmchan = ftdm_span_get_channel(span, chan_id); } else { /* invalid channel id */ @@ -1042,22 +1056,22 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic if (FTDM_SPAN_IS_NT(span)) { ftdm_log(FTDM_LOG_NOTICE, "No destination number found, assuming overlap dial\n"); overlap_dial++; - } - else { + } else { ftdm_log(FTDM_LOG_ERROR, "No destination number found\n"); ftdmchan = NULL; } } if (ftdmchan) { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE) || ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) { - if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN || ftdmchan->state >= FTDM_CHANNEL_STATE_TERMINATING) { + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE) || ftdm_channel_get_state(ftdmchan) != FTDM_CHANNEL_STATE_DOWN) { + if (ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DOWN || ftdm_channel_get_state(ftdmchan) >= FTDM_CHANNEL_STATE_TERMINATING) + { int x = 0; ftdm_log(FTDM_LOG_WARNING, "Channel %d:%d ~ %d:%d is already in use waiting for it to become available.\n", - ftdmchan->span_id, - ftdmchan->chan_id, - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id); + ftdm_channel_get_span_id(ftdmchan), + ftdm_channel_get_id(ftdmchan), + ftdm_channel_get_ph_span_id(ftdmchan), + ftdm_channel_get_ph_id(ftdmchan)); for (x = 0; x < 200; x++) { if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { @@ -1068,16 +1082,17 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic } if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { ftdm_log(FTDM_LOG_ERROR, "Channel %d:%d ~ %d:%d is already in use.\n", - ftdmchan->span_id, - ftdmchan->chan_id, - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id - ); + ftdm_channel_get_span_id(ftdmchan), + ftdm_channel_get_id(ftdmchan), + ftdm_channel_get_ph_span_id(ftdmchan), + ftdm_channel_get_ph_id(ftdmchan)); ftdmchan = NULL; } } - if (ftdmchan && ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) { + if (ftdmchan && ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DOWN) { + ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(ftdmchan); + isdn_data->channels_remote_crv[gen->CRV] = ftdmchan; memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data)); @@ -1086,34 +1101,32 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic } /* copy number readd prefix as needed */ - isdn_get_number(callingnum, ftdmchan->caller_data.cid_num.digits); - isdn_get_number(callingnum, ftdmchan->caller_data.cid_name); - isdn_get_number(callingnum, ftdmchan->caller_data.ani.digits); + isdn_get_number(callingnum, caller_data->cid_num.digits); + isdn_get_number(callingnum, caller_data->cid_name); + isdn_get_number(callingnum, caller_data->ani.digits); -// ftdm_set_string(ftdmchan->caller_data.cid_num.digits, (char *)callingnum->Digit); -// ftdm_set_string(ftdmchan->caller_data.cid_name, (char *)callingnum->Digit); -// ftdm_set_string(ftdmchan->caller_data.ani.digits, (char *)callingnum->Digit); if (!overlap_dial) { -// ftdm_set_string(ftdmchan->caller_data.dnis.digits, (char *)callednum->Digit); - isdn_get_number(callednum, ftdmchan->caller_data.dnis.digits); + isdn_get_number(callednum, caller_data->dnis.digits); } #ifdef __TODO_OR_REMOVE__ ftdmchan->caller_data.CRV = gen->CRV; #endif - if (cplen > sizeof(ftdmchan->caller_data.raw_data)) { - cplen = sizeof(ftdmchan->caller_data.raw_data); + if (cplen > sizeof(caller_data->raw_data)) { + cplen = sizeof(caller_data->raw_data); } gen->CRVFlag = !(gen->CRVFlag); - memcpy(ftdmchan->caller_data.raw_data, msg, cplen); - ftdmchan->caller_data.raw_data_len = cplen; + memcpy(caller_data->raw_data, msg, cplen); + caller_data->raw_data_len = cplen; fail = 0; } } if (fail) { Q931ie_Cause cause; + gen->MesType = Q931mes_DISCONNECT; gen->CRVFlag = 1; /* inbound call */ + cause.IEId = Q931ie_CAUSE; cause.Size = sizeof(Q931ie_Cause); cause.CodStand = Q931_CODING_ITU; @@ -1144,12 +1157,12 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic Q931InitIEChanID(&ChanID); ChanID.IntType = FTDM_SPAN_IS_BRI(ftdmchan->span) ? 0 : 1; /* PRI = 1, BRI = 0 */ ChanID.PrefExcl = FTDM_SPAN_IS_NT(ftdmchan->span) ? 1 : 0; /* Exclusive in NT-mode = 1, Preferred otherwise = 0 */ - if(ChanID.IntType) { + if (ChanID.IntType) { ChanID.InfoChanSel = 1; /* None = 0, See Slot = 1, Any = 3 */ ChanID.ChanMapType = 3; /* B-Chan */ - ChanID.ChanSlot = (unsigned char)ftdmchan->chan_id; + ChanID.ChanSlot = (unsigned char)ftdm_channel_get_id(ftdmchan); } else { - ChanID.InfoChanSel = (unsigned char)ftdmchan->chan_id & 0x03; /* None = 0, B1 = 1, B2 = 2, Any = 3 */ + ChanID.InfoChanSel = (unsigned char)ftdm_channel_get_id(ftdmchan) & 0x03; /* None = 0, B1 = 1, B2 = 2, Any = 3 */ } gen->ChanID = Q931AppendIE(gen, (L3UCHAR *) &ChanID); @@ -1187,7 +1200,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic case Q931mes_CALL_PROCEEDING: { if (ftdmchan) { - ftdm_log(FTDM_LOG_CRIT, "Received CALL PROCEEDING message for channel %d\n", chan_id); + ftdm_log(FTDM_LOG_CRIT, "Received CALL PROCEEDING message for channel %d\n", ftdm_channel_get_id(ftdmchan)); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); } else { ftdm_log(FTDM_LOG_CRIT, "Received CALL PROCEEDING with no matching channel %d\n", chan_id); @@ -1197,7 +1210,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic case Q931mes_CONNECT_ACKNOWLEDGE: { if (ftdmchan) { - ftdm_log(FTDM_LOG_DEBUG, "Received CONNECT_ACK message for channel %d\n", chan_id); + ftdm_log(FTDM_LOG_DEBUG, "Received CONNECT_ACK message for channel %d\n", ftdm_channel_get_id(ftdmchan)); } else { ftdm_log(FTDM_LOG_DEBUG, "Received CONNECT_ACK with no matching channel %d\n", chan_id); } @@ -1207,9 +1220,9 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic case Q931mes_INFORMATION: { if (ftdmchan) { - ftdm_log(FTDM_LOG_CRIT, "Received INFORMATION message for channel %d\n", ftdmchan->chan_id); + ftdm_log(FTDM_LOG_CRIT, "Received INFORMATION message for channel %d\n", ftdm_channel_get_id(ftdmchan)); - if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALTONE) { + if (ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DIALTONE) { char digit = '\0'; /* @@ -1227,7 +1240,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic /* TODO: make this more safe with strncat() */ pos = strlen(ftdmchan->caller_data.dnis.digits); - strcat(&ftdmchan->caller_data.dnis.digits[pos], (char *)callednum->Digit); + strcat(&ftdmchan->caller_data.dnis.digits[pos], (char *)callednum->Digit); /* update timer */ data->digit_timeout = ftdm_time_now() + isdn_data->digit_timeout; @@ -1307,14 +1320,16 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) ftdm_status_t status; ftdm_log(FTDM_LOG_DEBUG, "%d:%d STATE [%s]\n", - ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state)); + ftdm_channel_get_span_id(ftdmchan), + ftdm_channel_get_id(ftdmchan), + ftdm_channel_get_state_str(ftdmchan)); memset(&sig, 0, sizeof(sig)); - sig.chan_id = ftdmchan->chan_id; - sig.span_id = ftdmchan->span_id; + sig.span_id = ftdm_channel_get_span_id(ftdmchan); + sig.chan_id = ftdm_channel_get_id(ftdmchan); sig.channel = ftdmchan; - switch (ftdmchan->state) { + switch (ftdm_channel_get_state(ftdmchan)) { case FTDM_CHANNEL_STATE_DOWN: { if (gen->CRV) { @@ -1343,22 +1358,22 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) gen->CRV = crv; gen->CRVFlag = 1; /* inbound */ - if (FTDM_SPAN_IS_NT(ftdmchan->span)) { + if (FTDM_SPAN_IS_NT(ftdm_channel_get_span(ftdmchan))) { Q931ie_ChanID ChanID; /* * Set new Channel ID */ Q931InitIEChanID(&ChanID); - ChanID.IntType = FTDM_SPAN_IS_BRI(ftdmchan->span) ? 0 : 1; /* PRI = 1, BRI = 0 */ + ChanID.IntType = FTDM_SPAN_IS_BRI(ftdm_channel_get_span(ftdmchan)) ? 0 : 1; /* PRI = 1, BRI = 0 */ ChanID.PrefExcl = 1; /* always exclusive in NT-mode */ - if(ChanID.IntType) { + if (ChanID.IntType) { ChanID.InfoChanSel = 1; /* None = 0, See Slot = 1, Any = 3 */ ChanID.ChanMapType = 3; /* B-Chan */ - ChanID.ChanSlot = (unsigned char)ftdmchan->chan_id; + ChanID.ChanSlot = (unsigned char)ftdm_channel_get_id(ftdmchan); } else { - ChanID.InfoChanSel = (unsigned char)ftdmchan->chan_id & 0x03; /* None = 0, B1 = 1, B2 = 2, Any = 3 */ + ChanID.InfoChanSel = (unsigned char)ftdm_channel_get_id(ftdmchan) & 0x03; /* None = 0, B1 = 1, B2 = 2, Any = 3 */ } gen->ChanID = Q931AppendIE(gen, (L3UCHAR *) &ChanID); } @@ -1437,6 +1452,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) break; case FTDM_CHANNEL_STATE_DIALING: if (!(isdn_data->opts & FTDM_ISDN_OPT_SUGGEST_CHANNEL)) { + ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(ftdmchan); Q931ie_BearerCap BearerCap; Q931ie_ChanID ChanID; Q931ie_CallingNum CallingNum; @@ -1451,7 +1467,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) /* * get codec type */ - ftdm_channel_command(ftdmchan->span->channels[ftdmchan->chan_id], FTDM_COMMAND_GET_NATIVE_CODEC, &codec); + ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_NATIVE_CODEC, &codec); /* * Q.931 Setup Message @@ -1476,14 +1492,14 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) * ChannelID IE */ Q931InitIEChanID(&ChanID); - ChanID.IntType = FTDM_SPAN_IS_BRI(ftdmchan->span) ? 0 : 1; /* PRI = 1, BRI = 0 */ - ChanID.PrefExcl = FTDM_SPAN_IS_NT(ftdmchan->span) ? 1 : 0; /* Exclusive in NT-mode = 1, Preferred otherwise = 0 */ - if(ChanID.IntType) { + ChanID.IntType = FTDM_SPAN_IS_BRI(ftdm_channel_get_span(ftdmchan)) ? 0 : 1; /* PRI = 1, BRI = 0 */ + ChanID.PrefExcl = FTDM_SPAN_IS_NT(ftdm_channel_get_span(ftdmchan)) ? 1 : 0; /* Exclusive in NT-mode = 1, Preferred otherwise = 0 */ + if (ChanID.IntType) { ChanID.InfoChanSel = 1; /* None = 0, See Slot = 1, Any = 3 */ ChanID.ChanMapType = 3; /* B-Chan */ - ChanID.ChanSlot = (unsigned char)ftdmchan->chan_id; + ChanID.ChanSlot = (unsigned char)ftdm_channel_get_id(ftdmchan); } else { - ChanID.InfoChanSel = (unsigned char)ftdmchan->chan_id & 0x03; /* None = 0, B1 = 1, B2 = 2, Any = 3 */ + ChanID.InfoChanSel = (unsigned char)ftdm_channel_get_id(ftdmchan) & 0x03; /* None = 0, B1 = 1, B2 = 2, Any = 3 */ } gen->ChanID = Q931AppendIE(gen, (L3UCHAR *) &ChanID); @@ -1499,26 +1515,26 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) /* * Display IE */ - if (!(isdn_data->opts & FTDM_ISDN_OPT_OMIT_DISPLAY_IE) && FTDM_SPAN_IS_NT(ftdmchan->span)) { + if (!(isdn_data->opts & FTDM_ISDN_OPT_OMIT_DISPLAY_IE) && FTDM_SPAN_IS_NT(ftdm_channel_get_span(ftdmchan))) { Q931InitIEDisplay(&Display); - Display.Size = Display.Size + (unsigned char)strlen(ftdmchan->caller_data.cid_name); + Display.Size = Display.Size + (unsigned char)strlen(caller_data->cid_name); gen->Display = Q931AppendIE(gen, (L3UCHAR *) &Display); ptrDisplay = Q931GetIEPtr(gen->Display, gen->buf); - ftdm_copy_string((char *)ptrDisplay->Display, ftdmchan->caller_data.cid_name, strlen(ftdmchan->caller_data.cid_name)+1); + ftdm_copy_string((char *)ptrDisplay->Display, caller_data->cid_name, strlen(caller_data->cid_name) + 1); } /* * CallingNum IE */ Q931InitIECallingNum(&CallingNum); - CallingNum.TypNum = ftdmchan->caller_data.ani.type; + CallingNum.TypNum = caller_data->ani.type; CallingNum.NumPlanID = Q931_NUMPLAN_E164; CallingNum.PresInd = Q931_PRES_ALLOWED; CallingNum.ScreenInd = Q931_SCREEN_USER_NOT_SCREENED; - CallingNum.Size = CallingNum.Size + (unsigned char)strlen(ftdmchan->caller_data.cid_num.digits); + CallingNum.Size = CallingNum.Size + (unsigned char)strlen(caller_data->cid_num.digits); gen->CallingNum = Q931AppendIE(gen, (L3UCHAR *) &CallingNum); ptrCallingNum = Q931GetIEPtr(gen->CallingNum, gen->buf); - ftdm_copy_string((char *)ptrCallingNum->Digit, ftdmchan->caller_data.cid_num.digits, strlen(ftdmchan->caller_data.cid_num.digits)+1); + ftdm_copy_string((char *)ptrCallingNum->Digit, caller_data->cid_num.digits, strlen(caller_data->cid_num.digits) + 1); /* * CalledNum IE @@ -1526,10 +1542,10 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) Q931InitIECalledNum(&CalledNum); CalledNum.TypNum = Q931_TON_UNKNOWN; CalledNum.NumPlanID = Q931_NUMPLAN_E164; - CalledNum.Size = CalledNum.Size + (unsigned char)strlen(ftdmchan->caller_data.ani.digits); + CalledNum.Size = CalledNum.Size + (unsigned char)strlen(caller_data->ani.digits); gen->CalledNum = Q931AppendIE(gen, (L3UCHAR *) &CalledNum); ptrCalledNum = Q931GetIEPtr(gen->CalledNum, gen->buf); - ftdm_copy_string((char *)ptrCalledNum->Digit, ftdmchan->caller_data.ani.digits, strlen(ftdmchan->caller_data.ani.digits)+1); + ftdm_copy_string((char *)ptrCalledNum->Digit, caller_data->ani.digits, strlen(caller_data->ani.digits) + 1); /* * High-Layer Compatibility IE (Note: Required for AVM FritzBox) @@ -1554,7 +1570,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) call = Q931GetCallByCRV(&isdn_data->q931, gen->CRV); if (call) { ftdm_log(FTDM_LOG_DEBUG, "Storing reference to current span in call %d [0x%x]\n", gen->CRV, gen->CRV); - Q931CallSetPrivate(call, ftdmchan->span); + Q931CallSetPrivate(call, ftdm_channel_get_span(ftdmchan)); } } } @@ -1562,7 +1578,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: { /* reply RELEASE with RELEASE_COMPLETE message */ - if(ftdmchan->last_state == FTDM_CHANNEL_STATE_HANGUP) { + if (ftdm_channel_get_last_state(ftdmchan) == FTDM_CHANNEL_STATE_HANGUP) { gen->MesType = Q931mes_RELEASE_COMPLETE; Q931Rx43(&isdn_data->q931, gen, gen->Size); @@ -1572,6 +1588,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) break; case FTDM_CHANNEL_STATE_HANGUP: { + ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(ftdmchan); Q931ie_Cause cause; ftdm_log(FTDM_LOG_DEBUG, "Hangup: Direction %s\n", ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? "Outbound" : "Inbound"); @@ -1588,7 +1605,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) * BRI PTMP needs special handling here... * TODO: cleanup / refine (see above) */ - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_RING) { + if (ftdm_channel_get_last_state(ftdmchan) == FTDM_CHANNEL_STATE_RING) { /* * inbound call [was: number unknown (= not found in routing state)] * (in Q.931 spec terms: Reject request) @@ -1596,7 +1613,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) gen->MesType = Q931mes_RELEASE_COMPLETE; //cause.Value = (unsigned char) FTDM_CAUSE_UNALLOCATED; - cause.Value = (unsigned char) ftdmchan->caller_data.hangup_cause; + cause.Value = (unsigned char) caller_data->hangup_cause; *cause.Diag = '\0'; gen->Cause = Q931AppendIE(gen, (L3UCHAR *) &cause); Q931Rx43(&isdn_data->q931, gen, gen->Size); @@ -1605,13 +1622,13 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) //ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } - else if (ftdmchan->last_state <= FTDM_CHANNEL_STATE_PROGRESS) { + else if (ftdm_channel_get_last_state(ftdmchan) <= FTDM_CHANNEL_STATE_PROGRESS) { /* * just release all unanswered calls [was: inbound call, remote side hung up before we answered] */ gen->MesType = Q931mes_RELEASE; - cause.Value = (unsigned char) ftdmchan->caller_data.hangup_cause; + cause.Value = (unsigned char) caller_data->hangup_cause; *cause.Diag = '\0'; gen->Cause = Q931AppendIE(gen, (L3UCHAR *) &cause); Q931Rx43(&isdn_data->q931, gen, gen->Size); @@ -1625,7 +1642,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) */ gen->MesType = Q931mes_DISCONNECT; - cause.Value = (unsigned char) ftdmchan->caller_data.hangup_cause; + cause.Value = (unsigned char) caller_data->hangup_cause; *cause.Diag = '\0'; gen->Cause = Q931AppendIE(gen, (L3UCHAR *) &cause); Q931Rx43(&isdn_data->q931, gen, gen->Size); @@ -1638,6 +1655,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) sig.event_id = FTDM_SIGEVENT_STOP; status = isdn_data->sig_cb(&sig); + gen->MesType = Q931mes_RELEASE; gen->CRVFlag = ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? 0 : 1; Q931Rx43(&isdn_data->q931, gen, gen->Size); @@ -1649,19 +1667,25 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) static __inline__ void 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 <= ftdm_span_get_chan_count(span); j++) { + ftdm_channel_t *chan = ftdm_span_get_channel(span, j); + + if (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) { + ftdm_channel_lock(chan); + + ftdm_clear_flag(chan, FTDM_CHANNEL_STATE_CHANGE); + state_advance(chan); + ftdm_channel_complete_state(chan); + + ftdm_channel_unlock(chan); + } + } + } } @@ -1672,27 +1696,33 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e ftdm_sigmsg_t sig; memset(&sig, 0, sizeof(sig)); - sig.chan_id = event->channel->chan_id; - sig.span_id = event->channel->span_id; + sig.span_id = ftdm_channel_get_span_id(event->channel); + sig.chan_id = ftdm_channel_get_id(event->channel); sig.channel = event->channel; ftdm_log(FTDM_LOG_DEBUG, "EVENT [%s][%d:%d] STATE [%s]\n", - ftdm_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id, ftdm_channel_state2str(event->channel->state)); + ftdm_oob_event2str(event->enum_id), + ftdm_channel_get_span_id(event->channel), + ftdm_channel_get_id(event->channel), + ftdm_channel_get_state_str(event->channel)); - switch(event->enum_id) { + switch (event->enum_id) { case FTDM_OOB_ALARM_TRAP: { sig.event_id = FTDM_OOB_ALARM_TRAP; - if (event->channel->state != FTDM_CHANNEL_STATE_DOWN) { + if (ftdm_channel_get_state(event->channel) != FTDM_CHANNEL_STATE_DOWN) { ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RESTART); } ftdm_set_flag(event->channel, FTDM_CHANNEL_SUSPENDED); ftdm_channel_get_alarms(event->channel, &alarmbits); isdn_data->sig_cb(&sig); + ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) has alarms [%s]\n", - event->channel->span_id, event->channel->chan_id, - event->channel->physical_span_id, event->channel->physical_chan_id, - event->channel->last_error); + ftdm_channel_get_span_id(event->channel), + ftdm_channel_get_id(event->channel), + ftdm_channel_get_ph_span_id(event->channel), + ftdm_channel_get_ph_id(event->channel), + ftdm_channel_get_last_error(event->channel)); } break; case FTDM_OOB_ALARM_CLEAR: @@ -1708,7 +1738,7 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e { const char * digit_str = (const char *)event->data; - if(digit_str) { + if (digit_str) { fio_event_cb_t event_callback = NULL; ftdm_channel_queue_dtmf(event->channel, digit_str); @@ -1739,14 +1769,13 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e static __inline__ void check_events(ftdm_span_t *span) { - ftdm_status_t status; + ftdm_status_t status = ftdm_span_poll_event(span, 5, NULL); - status = ftdm_span_poll_event(span, 5, NULL); - - switch(status) { + switch (status) { case FTDM_SUCCESS: { ftdm_event_t *event; + while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) { if (event->enum_id == FTDM_OOB_NOOP) { continue; @@ -1776,6 +1805,7 @@ static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map if (!dt_buffer) { return -1; } + wrote = teletone_mux_tones(ts, map); ftdm_buffer_write(dt_buffer, ts->buffer, wrote * 2); return 0; @@ -1802,9 +1832,11 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj) ftdm_buffer_set_loops(dt_buffer, -1); /* get a tone generation friendly interval to avoid distortions */ - for (x = 1; x <= span->chan_count; x++) { - if (span->channels[x]->type != FTDM_CHAN_TYPE_DQ921) { - ftdm_channel_command(span->channels[x], FTDM_COMMAND_GET_INTERVAL, &interval); + for (x = 1; x <= ftdm_span_get_chan_count(span); x++) { + ftdm_channel_t *chan = ftdm_span_get_channel(span, x); + + if (ftdm_channel_get_type(chan) != FTDM_CHAN_TYPE_DQ921) { + ftdm_channel_command(chan, FTDM_COMMAND_GET_INTERVAL, &interval); break; } } @@ -1819,7 +1851,7 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj) ts.duration = ts.rate; /* main loop */ - while(ftdm_running() && ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { + while (ftdm_running() && ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { ftdm_wait_flag_t flags; ftdm_status_t status; int last_chan_state = 0; @@ -1829,11 +1861,11 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj) /* * check b-channel states and generate & send tones if neccessary */ - for (x = 1; x <= span->chan_count; x++) { - ftdm_channel_t *ftdmchan = span->channels[x]; + for (x = 1; x <= ftdm_span_get_chan_count(span); x++) { + ftdm_channel_t *chan = ftdm_span_get_channel(span, x); ftdm_size_t len = sizeof(frame), rlen; - if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) { + if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_DQ921) { continue; } @@ -1842,40 +1874,41 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj) * (Recycle buffer content if succeeding channels share the * same state, this saves some cpu cycles) */ - switch (ftdmchan->state) { + switch (ftdm_channel_get_state(chan)) { case FTDM_CHANNEL_STATE_DIALTONE: { - ftdm_isdn_bchan_data_t *data = (ftdm_isdn_bchan_data_t *)ftdmchan->mod_data; + ftdm_isdn_bchan_data_t *data = (ftdm_isdn_bchan_data_t *)chan->mod_data; + ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); /* check overlap dial timeout first before generating tone */ if (data && data->digit_timeout && data->digit_timeout <= now) { - if (strlen(ftdmchan->caller_data.dnis.digits) > 0) { + if (strlen(caller_data->dnis.digits) > 0) { ftdm_log(FTDM_LOG_DEBUG, "Overlap dial timeout, advancing to RING state\n"); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); + ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RING); } else { /* no digits received, hangup */ ftdm_log(FTDM_LOG_DEBUG, "Overlap dial timeout, no digits received, going to HANGUP state\n"); - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_RECOVERY_ON_TIMER_EXPIRE; /* TODO: probably wrong cause value */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); + caller_data->hangup_cause = FTDM_CAUSE_RECOVERY_ON_TIMER_EXPIRE; /* TODO: probably wrong cause value */ + ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP); } data->digit_timeout = 0; continue; } - if (last_chan_state != ftdmchan->state) { + if (last_chan_state != ftdm_channel_get_state(chan)) { ftdm_buffer_zero(dt_buffer); - teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_DIAL]); - last_chan_state = ftdmchan->state; + teletone_run(&ts, span->tone_map[FTDM_TONEMAP_DIAL]); + last_chan_state = ftdm_channel_get_state(chan); } } break; case FTDM_CHANNEL_STATE_RING: { - if (last_chan_state != ftdmchan->state) { + if (last_chan_state != ftdm_channel_get_state(chan)) { ftdm_buffer_zero(dt_buffer); - teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_RING]); - last_chan_state = ftdmchan->state; + teletone_run(&ts, span->tone_map[FTDM_TONEMAP_RING]); + last_chan_state = ftdm_channel_get_state(chan); } } break; @@ -1884,18 +1917,20 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj) continue; } - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); + if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) { + if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) { + ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP); continue; } - ftdm_log(FTDM_LOG_NOTICE, "Successfully opened channel %d:%d\n", ftdmchan->span_id, ftdmchan->chan_id); + ftdm_log(FTDM_LOG_NOTICE, "Successfully opened channel %d:%d\n", + ftdm_channel_get_span_id(chan), + ftdm_channel_get_id(chan)); } flags = FTDM_READ; - status = ftdm_channel_wait(ftdmchan, &flags, (gated) ? 0 : interval); - switch(status) { + status = ftdm_channel_wait(chan, &flags, (gated) ? 0 : interval); + switch (status) { case FTDM_FAIL: continue; @@ -1910,12 +1945,12 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj) } gated = 1; - status = ftdm_channel_read(ftdmchan, frame, &len); + status = ftdm_channel_read(chan, frame, &len); if (status != FTDM_SUCCESS || len <= 0) { continue; } - if (ftdmchan->effective_codec != FTDM_CODEC_SLIN) { + if (chan->effective_codec != FTDM_CODEC_SLIN) { len *= 2; } @@ -1924,23 +1959,23 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj) rlen = ftdm_buffer_read_loop(dt_buffer, frame, len); - if (ftdmchan->effective_codec != FTDM_CODEC_SLIN) { + if (chan->effective_codec != FTDM_CODEC_SLIN) { fio_codec_t codec_func = NULL; - if (ftdmchan->native_codec == FTDM_CODEC_ULAW) { + if (chan->native_codec == FTDM_CODEC_ULAW) { codec_func = fio_slin2ulaw; - } else if (ftdmchan->native_codec == FTDM_CODEC_ALAW) { + } else if (chan->native_codec == FTDM_CODEC_ALAW) { codec_func = fio_slin2alaw; } if (codec_func) { status = codec_func(frame, sizeof(frame), &rlen); } else { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!"); + snprintf(chan->last_error, sizeof(chan->last_error), "codec error!"); goto done; } } - ftdm_channel_write(ftdmchan, frame, sizeof(frame), &rlen); + ftdm_channel_write(chan, frame, sizeof(frame), &rlen); } /* @@ -1989,7 +2024,7 @@ static void *ftdm_isdn_run(ftdm_thread_t *me, void *obj) Q921Start(&isdn_data->q921); Q931Start(&isdn_data->q931); - while(ftdm_running() && ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { + while (ftdm_running() && ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { ftdm_wait_flag_t flags = FTDM_READ; ftdm_status_t status = ftdm_channel_wait(isdn_data->dchan, &flags, 100); @@ -2001,7 +2036,7 @@ static void *ftdm_isdn_run(ftdm_thread_t *me, void *obj) /* * */ - switch(status) { + switch (status) { case FTDM_FAIL: { ftdm_log(FTDM_LOG_ERROR, "D-Chan Read Error!\n"); @@ -2040,8 +2075,8 @@ static void *ftdm_isdn_run(ftdm_thread_t *me, void *obj) } done: - ftdm_channel_close(&isdn_data->dchans[0]); - ftdm_channel_close(&isdn_data->dchans[1]); +// ftdm_channel_close(&isdn_data->dchans[0]); +// ftdm_channel_close(&isdn_data->dchans[1]); ftdm_clear_flag(isdn_data, FTDM_ISDN_RUNNING); #ifdef WIN32 @@ -2223,11 +2258,11 @@ static ftdm_status_t ftdm_isdn_stop(ftdm_span_t *span) ftdm_set_flag(isdn_data, FTDM_ISDN_STOP); - while(ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { + while (ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { ftdm_sleep(100); } - while(ftdm_test_flag(isdn_data, FTDM_ISDN_TONES_RUNNING)) { + while (ftdm_test_flag(isdn_data, FTDM_ISDN_TONES_RUNNING)) { ftdm_sleep(100); } @@ -2239,8 +2274,8 @@ static ftdm_status_t ftdm_isdn_stop(ftdm_span_t *span) */ static ftdm_status_t ftdm_isdn_start(ftdm_span_t *span) { - ftdm_status_t ret; ftdm_isdn_data_t *isdn_data = span->signal_data; + ftdm_status_t ret; if (ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { return FTDM_FAIL; @@ -2266,9 +2301,8 @@ static ftdm_status_t ftdm_isdn_start(ftdm_span_t *span) static int32_t parse_loglevel(const char *level) { - if (!level) { + if (!level) return -1; - } if (!strcasecmp(level, "debug")) { return FTDM_LOG_LEVEL_DEBUG; @@ -2291,53 +2325,53 @@ static int32_t parse_loglevel(const char *level) } } -static uint32_t parse_opts(const char *in) +static int parse_opts(const char *in, uint32_t *flags) { - uint32_t flags = 0; - - if (!in) { - return 0; - } + if (!in || !flags) + return -1; if (strstr(in, "suggest_channel")) { - flags |= FTDM_ISDN_OPT_SUGGEST_CHANNEL; + *flags |= FTDM_ISDN_OPT_SUGGEST_CHANNEL; } - if (strstr(in, "omit_display")) { - flags |= FTDM_ISDN_OPT_OMIT_DISPLAY_IE; + *flags |= FTDM_ISDN_OPT_OMIT_DISPLAY_IE; } - if (strstr(in, "disable_tones")) { - flags |= FTDM_ISDN_OPT_DISABLE_TONES; + *flags |= FTDM_ISDN_OPT_DISABLE_TONES; } - return flags; + return 0; } -static uint32_t parse_dialect(const char *in) +static int parse_dialect(const char *in, uint32_t *dialect) { - if (!in) { - return Q931_Dialect_Count; - } + if (!in || !dialect) + return -1; #if __UNSUPPORTED__ if (!strcasecmp(in, "national")) { - return Q931_Dialect_National; + *dialect = Q931_Dialect_National; + return 0; } if (!strcasecmp(in, "dms")) { - return Q931_Dialect_DMS; + *dialect = Q931_Dialect_DMS; + return 0; } #endif if (!strcasecmp(in, "5ess")) { - return Q931_Dialect_5ESS; + *dialect = Q931_Dialect_5ESS; + return 0; } - if (!strcasecmp(in, "dss1")) { - return Q931_Dialect_DSS1; + if (!strcasecmp(in, "dss1") || !strcasecmp(in, "euroisdn")) { + *dialect = Q931_Dialect_DSS1; + return 0; } if (!strcasecmp(in, "q931")) { - return Q931_Dialect_Q931; + *dialect = Q931_Dialect_Q931; + return 0; } - return Q931_Dialect_Count; + + return -1; } @@ -2425,7 +2459,7 @@ static FIO_API_FUNCTION(isdn_api) if (!strcasecmp(argv[2], "q921")) { layer = 0x01; - } else if(!strcasecmp(argv[2], "q931")) { + } else if (!strcasecmp(argv[2], "q931")) { layer = 0x02; } else if (!strcasecmp(argv[2], "all")) { layer = 0x03; @@ -2513,7 +2547,7 @@ static FIO_API_FUNCTION(isdn_api) stream->write_function(stream, "+OK capture started.\n"); goto done; } - else if(!strcasecmp(argv[2], "stop")) { + else if (!strcasecmp(argv[2], "stop")) { if (!isdn_pcap_is_open(isdn_data)) { stream->write_function(stream, "-ERR capture is not running.\n"); @@ -2526,7 +2560,7 @@ static FIO_API_FUNCTION(isdn_api) stream->write_function(stream, "+OK capture stopped.\n"); goto done; } - else if(!strcasecmp(argv[2], "suspend")) { + else if (!strcasecmp(argv[2], "suspend")) { if (!isdn_pcap_is_open(isdn_data)) { stream->write_function(stream, "-ERR capture is not running.\n"); @@ -2537,7 +2571,7 @@ static FIO_API_FUNCTION(isdn_api) stream->write_function(stream, "+OK capture suspended.\n"); goto done; } - else if(!strcasecmp(argv[2], "resume")) { + else if (!strcasecmp(argv[2], "resume")) { if (!isdn_pcap_is_open(isdn_data)) { stream->write_function(stream, "-ERR capture is not running.\n"); @@ -2563,44 +2597,80 @@ done: return FTDM_SUCCESS; } -static FIO_SIG_CONFIGURE_FUNCTION(isdn_configure_span) +static int parse_mode(const char *mode) +{ + if (!mode) + return -1; + + if (!strcasecmp(mode, "user") || !strcasecmp(mode, "cpe")) { + return Q931_TE; + } + if (!strcasecmp(mode, "net") || !strcasecmp(mode, "network")) { + return Q931_NT; + } + + return -1; +} + +static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(isdn_configure_span) { - uint32_t i, x = 0; - ftdm_channel_t *dchans[2] = { 0 }; - ftdm_isdn_data_t *isdn_data; - const char *tonemap = "us"; - char *var, *val; Q931Dialect_t dialect = Q931_Dialect_National; + ftdm_channel_t *dchan = NULL; + ftdm_isdn_data_t *isdn_data; int32_t digit_timeout = 0; + const char *tonemap = "us"; + int dchan_count = 0, bchan_count = 0; int q921loglevel = -1; int q931loglevel = -1; + uint32_t i; if (span->signal_type) { - snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling [%d].", span->signal_type); + ftdm_log(FTDM_LOG_ERROR, "Span is already configured for signalling [%d]\n", span->signal_type); + snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling [%d]", span->signal_type); return FTDM_FAIL; } - if (span->trunk_type >= FTDM_TRUNK_NONE) { - ftdm_log(FTDM_LOG_WARNING, "Invalid trunk type '%s' defaulting to T1.\n", ftdm_trunk_type2str(span->trunk_type)); + if (ftdm_span_get_trunk_type(span) >= FTDM_TRUNK_NONE) { + ftdm_log(FTDM_LOG_WARNING, "Invalid trunk type '%s' defaulting to T1\n", ftdm_span_get_trunk_type_str(span)); span->trunk_type = FTDM_TRUNK_T1; } - for(i = 1; i <= span->chan_count; i++) { - if (span->channels[i]->type == FTDM_CHAN_TYPE_DQ921) { - if (x > 1) { - snprintf(span->last_error, sizeof(span->last_error), "Span has more than 2 D-Channels!"); + for (i = 1; i <= ftdm_span_get_chan_count(span); i++) { + ftdm_channel_t *chan = ftdm_span_get_channel(span, i); + + switch (ftdm_channel_get_type(chan)) { + case FTDM_CHAN_TYPE_DQ921: + if (dchan_count > 1) { + ftdm_log(FTDM_LOG_ERROR, "Span has more than 1 D-Channel!\n"); + snprintf(span->last_error, sizeof(span->last_error), "Span has more than 1 D-Channel!"); return FTDM_FAIL; } - if (ftdm_channel_open(span->span_id, i, &dchans[x]) == FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_DEBUG, "opening d-channel #%d %d:%d\n", x, dchans[x]->span_id, dchans[x]->chan_id); - dchans[x]->state = FTDM_CHANNEL_STATE_UP; - x++; + if (ftdm_channel_open(ftdm_span_get_id(span), i, &dchan) == FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_DEBUG, "opening d-channel #%d %d:%d\n", dchan_count, + ftdm_channel_get_span_id(dchan), ftdm_channel_get_id(dchan)); + dchan->state = FTDM_CHANNEL_STATE_UP; } + + dchan_count++; + break; + + case FTDM_CHAN_TYPE_B: + bchan_count++; + break; + + default: + break; } } - if (!x) { - snprintf(span->last_error, sizeof(span->last_error), "Span has no D-Channels!"); + if (!dchan_count) { + ftdm_log(FTDM_LOG_ERROR, "Span has no D-Channel!\n"); + snprintf(span->last_error, sizeof(span->last_error), "Span has no D-Channel!"); + return FTDM_FAIL; + } + if (!bchan_count) { + ftdm_log(FTDM_LOG_ERROR, "Span has no B-Channels!\n"); + snprintf(span->last_error, sizeof(span->last_error), "Span has no B-Channels!"); return FTDM_FAIL; } @@ -2611,52 +2681,55 @@ static FIO_SIG_CONFIGURE_FUNCTION(isdn_configure_span) isdn_data->mode = Q931_TE; dialect = Q931_Dialect_Q931; - while((var = va_arg(ap, char *))) { + for (i = 0; ftdm_parameters[i].var; i++) { + const char *var = ftdm_parameters[i].var; + const char *val = ftdm_parameters[i].val; + + if (!val) { + ftdm_log(FTDM_LOG_ERROR, "Variable '%s' has no value\n", var); + return FTDM_FAIL; + } + if (!strcasecmp(var, "mode")) { - if (!(val = va_arg(ap, char *))) { - break; + if ((isdn_data->mode = parse_mode(val)) < 0) { + ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown mode '%s'\n", val); + snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown mode [%s]!", val); + return FTDM_FAIL; } - isdn_data->mode = strcasecmp(val, "net") ? Q931_TE : Q931_NT; } else if (!strcasecmp(var, "dialect")) { - if (!(val = va_arg(ap, char *))) { - break; - } - dialect = parse_dialect(val); - if (dialect == Q931_Dialect_Count) { + if (parse_dialect(val, &dialect) < 0) { + ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown dialect '%s'\n", val); snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown dialect [%s]!", val); return FTDM_FAIL; } } else if (!strcasecmp(var, "opts")) { - if (!(val = va_arg(ap, char *))) { - break; + if (parse_opts(val, &isdn_data->opts) < 0) { + ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown options '%s'\n", val); + snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown options [%s]!", val); + return FTDM_FAIL; } - isdn_data->opts = parse_opts(val); } else if (!strcasecmp(var, "tonemap")) { - if (!(val = va_arg(ap, char *))) { - break; - } tonemap = (const char *)val; } else if (!strcasecmp(var, "digit_timeout")) { - int *optp; - if (!(optp = va_arg(ap, int *))) { - break; + digit_timeout = atoi(val); + if (digit_timeout < 3000 || digit_timeout > 30000) { + ftdm_log(FTDM_LOG_WARNING, "Digit timeout %d ms outside of range (3000 - 30000 ms), using default (10000 ms)\n", digit_timeout); + digit_timeout = DEFAULT_DIGIT_TIMEOUT; } - digit_timeout = *optp; } else if (!strcasecmp(var, "q921loglevel")) { - q921loglevel = va_arg(ap, int); - if (q921loglevel < Q921_LOG_NONE) { - q921loglevel = Q921_LOG_NONE; - } else if (q921loglevel > Q921_LOG_DEBUG) { - q921loglevel = Q921_LOG_DEBUG; + if ((q921loglevel = parse_loglevel(val)) < 0) { + ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown loglevel '%s'\n", val); + snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown loglevel [%s]!", val); + return FTDM_FAIL; } } else if (!strcasecmp(var, "q931loglevel")) { - q931loglevel = va_arg(ap, int); - if (q931loglevel < Q931_LOG_NONE) { - q931loglevel = Q931_LOG_NONE; - } else if (q931loglevel > Q931_LOG_DEBUG) { - q931loglevel = Q931_LOG_DEBUG; + if ((q931loglevel = parse_loglevel(val)) < 0) { + ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown loglevel '%s'\n", val); + snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown loglevel [%s]!", val); + return FTDM_FAIL; } } else { + ftdm_log(FTDM_LOG_ERROR, "Unknown parameter '%s'\n", var); snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var); return FTDM_FAIL; } @@ -2665,39 +2738,35 @@ static FIO_SIG_CONFIGURE_FUNCTION(isdn_configure_span) if (!digit_timeout) { digit_timeout = DEFAULT_DIGIT_TIMEOUT; } - else if (digit_timeout < 3000 || digit_timeout > 30000) { - ftdm_log(FTDM_LOG_WARNING, "Digit timeout %d ms outside of range (3000 - 30000 ms), using default (10000 ms)\n", digit_timeout); - digit_timeout = DEFAULT_DIGIT_TIMEOUT; - } /* allocate per b-chan data */ if (isdn_data->mode == Q931_NT) { ftdm_isdn_bchan_data_t *data; - data = malloc(span->chan_count * sizeof(ftdm_isdn_bchan_data_t)); + data = malloc(bchan_count * sizeof(ftdm_isdn_bchan_data_t)); if (!data) { return FTDM_FAIL; } - for (i = 1; i <= span->chan_count; i++, data++) { - if (span->channels[i]->type == FTDM_CHAN_TYPE_B) { - span->channels[i]->mod_data = data; + for (i = 1; i <= ftdm_span_get_chan_count(span); i++, data++) { + ftdm_channel_t *chan = ftdm_span_get_channel(span, i); + + if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_B) { + chan->mod_data = data; memset(data, 0, sizeof(ftdm_isdn_bchan_data_t)); } } } - isdn_data->sig_cb = sig_cb; - isdn_data->dchans[0] = dchans[0]; - isdn_data->dchans[1] = dchans[1]; - isdn_data->dchan = isdn_data->dchans[0]; + isdn_data->sig_cb = sig_cb; + isdn_data->dchan = dchan; isdn_data->digit_timeout = digit_timeout; Q921_InitTrunk(&isdn_data->q921, 0, 0, isdn_data->mode, - span->trunk_type == FTDM_TRUNK_BRI_PTMP ? Q921_PTMP : Q921_PTP, + (ftdm_span_get_trunk_type(span) == FTDM_TRUNK_BRI_PTMP) ? Q921_PTMP : Q921_PTP, 0, ftdm_isdn_921_21, (Q921Tx23CB_t)ftdm_isdn_921_23, @@ -2798,7 +2867,7 @@ ftdm_module_t ftdm_module = { .io_unload = NULL, .sig_load = isdn_load, .sig_unload = isdn_unload, - .sig_configure = isdn_configure_span + .configure_span_signaling = isdn_configure_span }; /* For Emacs: