Merge branch 'master' into arnaldo.zt_chan_next_event

This commit is contained in:
Arnaldo Pereira committed 2010-12-21 14:16:45 -02:00
commit 7732a67598
132 files changed
+10229 -1269

No files matched your search

@@ -96,6 +96,10 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxs_outgoing_call)
static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(analog_get_channel_sig_status)
{
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) {
*status = FTDM_SIG_STATE_DOWN;
return FTDM_SUCCESS;
}
*status = FTDM_SIG_STATE_UP;
return FTDM_SUCCESS;
}
@@ -109,7 +113,25 @@ static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(analog_get_channel_sig_status)
static FIO_SPAN_GET_SIG_STATUS_FUNCTION(analog_get_span_sig_status)
{
*status = FTDM_SIG_STATE_UP;
ftdm_iterator_t *citer = NULL;
ftdm_iterator_t *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;
}
/* if ALL channels are in alarm, report DOWN, UP otherwise. */
*status = FTDM_SIG_STATE_DOWN;
for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) {
ftdm_channel_t *fchan = ftdm_iterator_current(citer);
ftdm_channel_lock(fchan);
if (!ftdm_test_flag(fchan, FTDM_CHANNEL_IN_ALARM)) {
*status = FTDM_SIG_STATE_UP;
ftdm_channel_unlock(fchan);
break;
}
ftdm_channel_unlock(fchan);
}
ftdm_iterator_free(chaniter);
return FTDM_SUCCESS;
}
@@ -491,9 +513,12 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
ftdm_channel_command(ftdmchan, FTDM_COMMAND_GENERATE_RING_OFF, NULL);
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) &&
(ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
|| ftdmchan->last_state >= FTDM_CHANNEL_STATE_RING)) {
if (ftdmchan->type == FTDM_CHAN_TYPE_FXS &&
ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) &&
(ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING
|| ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
|| ftdmchan->last_state == FTDM_CHANNEL_STATE_RING
|| ftdmchan->last_state == FTDM_CHANNEL_STATE_UP)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
} else {
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING;
@@ -716,7 +741,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
dtmf_offset = strlen(dtmf);
last_digit = elapsed;
sig.event_id = FTDM_SIGEVENT_COLLECTED_DIGIT;
sig.raw_data = dtmf;
ftdm_set_string(sig.ev_data.collected.digits, dtmf);
if (ftdm_span_send_signal(ftdmchan->span, &sig) == FTDM_BREAK) {
collecting = 0;
}
@@ -883,14 +908,14 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
{
if (event->channel->type != FTDM_CHAN_TYPE_FXO) {
ftdm_log_chan_msg(event->channel, FTDM_LOG_ERROR, "Cannot get a RING_START event on a non-fxo channel, please check your config.\n");
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DOWN);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN);
goto end;
}
if (!event->channel->ring_count && (event->channel->state == FTDM_CHANNEL_STATE_DOWN && !ftdm_test_flag(event->channel, FTDM_CHANNEL_INTHREAD))) {
if (ftdm_test_flag(analog_data, FTDM_ANALOG_CALLERID)) {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID);
} else {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RING);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_RING);
}
event->channel->ring_count = 1;
ftdm_mutex_unlock(event->channel->mutex);
@@ -908,7 +933,12 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
}
if (event->channel->state != FTDM_CHANNEL_STATE_DOWN) {
ftdm_set_state_locked(event->channel, 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_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN);
}
}
@@ -916,16 +946,16 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
case FTDM_OOB_FLASH:
{
if (event->channel->state == FTDM_CHANNEL_STATE_CALLWAITING) {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_UP);
ftdm_clear_flag_locked(event->channel, FTDM_CHANNEL_STATE_CHANGE);
ftdm_clear_flag_locked(event->channel->span, FTDM_SPAN_STATE_CHANGE);
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);
event->channel->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK] = 0;
}
ftdm_channel_rotate_tokens(event->channel);
if (ftdm_test_flag(event->channel, FTDM_CHANNEL_HOLD) && event->channel->token_count != 1) {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_UP);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_UP);
} else {
sig.event_id = FTDM_SIGEVENT_FLASH;
ftdm_span_send_signal(span, &sig);
@@ -939,12 +969,12 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
if (ftdm_test_flag(event->channel, FTDM_CHANNEL_RINGING)) {
ftdm_channel_command(event->channel, FTDM_COMMAND_GENERATE_RING_OFF, NULL);
}
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_UP);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_UP);
} else {
if(!analog_data->max_dialstr) {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_COLLECT);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_COLLECT);
} else {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DIALTONE);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DIALTONE);
}
ftdm_mutex_unlock(event->channel->mutex);
locked = 0;
@@ -956,9 +986,24 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
ftdm_channel_command(event->channel, FTDM_COMMAND_ONHOOK, NULL);
}
}
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DOWN);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN);
}
}
break;
case FTDM_OOB_ALARM_TRAP:
{
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sig.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(span, &sig);
}
break;
case FTDM_OOB_ALARM_CLEAR:
{
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sig.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(span, &sig);
}
break;
default:
{
ftdm_log_chan(event->channel, FTDM_LOG_DEBUG, "Ignoring event [%s] in state [%s]\n", ftdm_oob_event2str(event->enum_id), ftdm_channel_state2str(event->channel->state));
@@ -329,8 +329,8 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
{
if (state_counter > 500) {
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) &&
(ftdmchan->last_state == FTDM_CHANNEL_STATE_RING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
|| ftdmchan->last_state >= FTDM_CHANNEL_STATE_IDLE)) {
(ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
|| ftdmchan->last_state == FTDM_CHANNEL_STATE_RING)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
} else {
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING;
@@ -340,7 +340,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
}
break;
case FTDM_CHANNEL_STATE_UP:
case FTDM_CHANNEL_STATE_IDLE:
case FTDM_CHANNEL_STATE_RING:
{
ftdm_sleep(interval);
continue;
@@ -386,7 +386,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
ftdm_channel_use(ftdmchan);
}
break;
case FTDM_CHANNEL_STATE_IDLE:
case FTDM_CHANNEL_STATE_RING:
{
ftdm_channel_use(ftdmchan);
@@ -421,7 +421,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
ftdm_channel_command(ftdmchan, FTDM_COMMAND_WINK, NULL);
}
break;
case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_RINGING:
{
ftdm_buffer_zero(dt_buffer);
teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_RING]);
@@ -467,7 +467,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
dtmf_offset = strlen(dtmf);
last_digit = elapsed;
sig.event_id = FTDM_SIGEVENT_COLLECTED_DIGIT;
sig.raw_data = dtmf;
ftdm_set_string(sig.ev_data.collected.digits, dtmf);
if (ftdm_span_send_signal(ftdmchan->span, &sig) == FTDM_BREAK) {
collecting = 0;
}
@@ -477,7 +477,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) > analog_data->max_dialstr))) {
ftdm_log(FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
last_digit = 0;
collecting = 0;
}
@@ -1325,7 +1325,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
}
Q931ReleaseCRV(&isdn_data->q931, gen->CRV);
}
ftdm_channel_done(ftdmchan);
ftdm_channel_close(&ftdmchan);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS:
@@ -515,23 +515,17 @@ static __inline__ void state_advance(ftdm_channel_t *chan)
switch (ftdm_channel_get_state(chan)) {
case FTDM_CHANNEL_STATE_DOWN:
{
ftdm_channel_t *chtmp = chan;
chan->call_data = NULL;
ftdm_channel_done(chan);
/*
* Close channel completely, BRI PTMP will thank us
*/
if (ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
ftdm_channel_t *chtmp = chan;
if (ftdm_channel_close(&chtmp) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_WARNING, "-- Failed to close channel %d:%d\n",
ftdm_channel_get_span_id(chan),
ftdm_channel_get_id(chan));
} else {
ftdm_log(FTDM_LOG_DEBUG, "-- Closed channel %d:%d\n",
ftdm_channel_get_span_id(chan),
ftdm_channel_get_id(chan));
}
if (ftdm_channel_close(&chtmp) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_WARNING, "-- Failed to close channel %d:%d\n",
ftdm_channel_get_span_id(chan),
ftdm_channel_get_id(chan));
} else {
ftdm_log(FTDM_LOG_DEBUG, "-- Closed channel %d:%d\n",
ftdm_channel_get_span_id(chan),
ftdm_channel_get_id(chan));
}
}
break;
@@ -1403,8 +1397,7 @@ static int on_dchan_up(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev
sig.chan_id = ftdm_channel_get_id(chan);
sig.channel = chan;
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sig.raw_data = &status;
sig.ev_data.sigstatus.status = status;
ftdm_span_send_signal(span, &sig);
}
}
@@ -1440,7 +1433,7 @@ static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_
sig.chan_id = ftdm_channel_get_id(chan);
sig.channel = chan;
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sig.raw_data = &status;
sig.ev_data.sigstatus.status = status;
ftdm_span_send_signal(span, &sig);
}
@@ -127,24 +127,24 @@ static int __pri_lpwrap_read(struct pri *pri, void *buf, int buflen)
} else {
ftdm_log(FTDM_LOG_CRIT, "span %d D-READ TIMEOUT\n", spri->span->span_id);
}
ftdm_clear_flag(spri, LPWRAP_PRI_READY);
return -1;
/* we cannot return -1, libpri seems to expect values >= 0 */
return 0;
}
spri->errs = 0;
res = (int)len;
memset(&((unsigned char*)buf)[res], 0, 2);
res += 2;
if (res > 0) {
memset(&((unsigned char*)buf)[res], 0, 2);
res += 2;
#ifdef IODEBUG
{
char bb[2048] = { 0 };
{
char bb[2048] = { 0 };
print_hex_bytes(buf, res - 2, bb, sizeof(bb));
ftdm_log(FTDM_LOG_DEBUG, "READ %d\n", res - 2);
}
print_hex_bytes(buf, res - 2, bb, sizeof(bb));
ftdm_log(FTDM_LOG_DEBUG, "READ %d\n", res - 2);
}
#endif
}
return res;
}
@@ -155,8 +155,8 @@ static int __pri_lpwrap_write(struct pri *pri, void *buf, int buflen)
if (ftdm_channel_write(spri->dchan, buf, buflen, &len) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "span %d D-WRITE FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error);
ftdm_clear_flag(spri, LPWRAP_PRI_READY);
return -1;
/* we cannot return -1, libpri seems to expect values >= 0 */
return 0;
}
#ifdef IODEBUG
@@ -280,12 +280,12 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_DOWN:
{
ftdm_channel_done(ftdmchan);
{
ftdmchan->call_data = NULL;
ftdm_channel_close(&ftdmchan);
ftdm_channel_done(peerchan);
peerchan->call_data = NULL;
ftdm_channel_close(&peerchan);
}
break;
+246 -50
View File
@@ -29,6 +29,12 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
*
* Arnaldo Pereira <arnaldo@sangoma.com>
* Ricardo Barroetaveña <rbarroetavena@anura.com.ar>
*
*/
#ifdef __linux__
@@ -44,16 +50,15 @@
#include "freetdm.h"
#include "private/ftdm_core.h"
/* debug thread count for r2 legs */
static ftdm_mutex_t* g_thread_count_mutex;
static int32_t g_thread_count = 0;
typedef int openr2_call_status_t;
/* when the users kills a span we clear this flag to kill the signaling thread */
/* when the user stops a span, we clear FTDM_R2_SPAN_STARTED, so that the signaling thread
* knows it must stop, and we wait for FTDM_R2_RUNNING to be clear, which tells us the
* signaling thread is done. */
/* FIXME: what about the calls that are already up-and-running? */
typedef enum {
FTDM_R2_RUNNING = (1 << 0),
FTDM_R2_SPAN_STARTED = (1 << 1),
} ftdm_r2_flag_t;
/* private call information stored in ftdmchan->call_data void* ptr,
@@ -250,7 +255,7 @@ static void ftdm_r2_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling
sig.span_id = ftdmchan->span_id;
sig.channel = ftdmchan;
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sig.sigstatus = status;
sig.ev_data.sigstatus.status = status;
if (ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to change channel status to %s\n", ftdm_signaling_status2str(status));
}
@@ -372,11 +377,72 @@ static void ft_r2_answer_call(ftdm_channel_t *ftdmchan)
R2CALL(ftdmchan)->answer_pending = 0;
}
static __inline__ ftdm_calling_party_category_t ftdm_openr2_cpc_to_r2_ftdm_cpc(openr2_calling_party_category_t cpc)
{
switch (cpc) {
case OR2_CALLING_PARTY_CATEGORY_UNKNOWN:
return FTDM_CPC_UNKNOWN;
case OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER:
return FTDM_CPC_ORDINARY;
case OR2_CALLING_PARTY_CATEGORY_NATIONAL_PRIORITY_SUBSCRIBER:
return FTDM_CPC_PRIORITY;
case OR2_CALLING_PARTY_CATEGORY_INTERNATIONAL_SUBSCRIBER:
return FTDM_CPC_UNKNOWN;
case OR2_CALLING_PARTY_CATEGORY_INTERNATIONAL_PRIORITY_SUBSCRIBER:
return FTDM_CPC_UNKNOWN;
case OR2_CALLING_PARTY_CATEGORY_TEST_EQUIPMENT:
return FTDM_CPC_TEST;
case OR2_CALLING_PARTY_CATEGORY_PAY_PHONE:
return FTDM_CPC_PAYPHONE;
case OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL:
return FTDM_CPC_OPERATOR;
}
return FTDM_CPC_INVALID;
}
static __inline openr2_calling_party_category_t ftdm_r2_ftdm_cpc_to_openr2_cpc(ftdm_calling_party_category_t cpc)
{
switch (cpc) {
case FTDM_CPC_UNKNOWN:
return OR2_CALLING_PARTY_CATEGORY_UNKNOWN;
case FTDM_CPC_OPERATOR:
return OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL;
case FTDM_CPC_ORDINARY:
return OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
case FTDM_CPC_PRIORITY:
return OR2_CALLING_PARTY_CATEGORY_NATIONAL_PRIORITY_SUBSCRIBER;
case FTDM_CPC_DATA:
return OR2_CALLING_PARTY_CATEGORY_UNKNOWN;
case FTDM_CPC_TEST:
return OR2_CALLING_PARTY_CATEGORY_TEST_EQUIPMENT;
case FTDM_CPC_PAYPHONE:
return OR2_CALLING_PARTY_CATEGORY_PAY_PHONE;
case FTDM_CPC_INVALID:
return OR2_CALLING_PARTY_CATEGORY_UNKNOWN;
}
return OR2_CALLING_PARTY_CATEGORY_UNKNOWN;
}
/* this function must be called with the chan mutex held! */
static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call)
{
openr2_call_status_t callstatus;
ftdm_r2_data_t *r2data;
openr2_calling_party_category_t category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
r2data = ftdmchan->span->signal_data;
@@ -389,6 +455,12 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call)
ft_r2_clean_call(ftdmchan->call_data);
if (ftdmchan->caller_data.cpc == FTDM_CPC_INVALID || ftdmchan->caller_data.cpc == FTDM_CPC_UNKNOWN) {
category = r2data->category;
} else {
category = ftdm_r2_ftdm_cpc_to_openr2_cpc(ftdmchan->caller_data.cpc);
}
/* start io dump */
if (r2data->mf_dump_size) {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_INPUT_DUMP, &r2data->mf_dump_size);
@@ -396,9 +468,9 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call)
}
callstatus = openr2_chan_make_call(R2CALL(ftdmchan)->r2chan,
ftdmchan->caller_data.cid_num.digits,
ftdmchan->caller_data.pres == FTDM_PRES_ALLOWED ? ftdmchan->caller_data.cid_num.digits : NULL,
ftdmchan->caller_data.dnis.digits,
r2data->category);
category);
if (callstatus) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to make call in R2 channel, openr2_chan_make_call failed\n");
@@ -419,13 +491,14 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call)
static ftdm_status_t ftdm_r2_start(ftdm_span_t *span)
{
ftdm_r2_data_t *r2_data = span->signal_data;
ftdm_set_flag(r2_data, FTDM_R2_RUNNING);
ftdm_set_flag(r2_data, FTDM_R2_SPAN_STARTED);
return ftdm_thread_create_detached(ftdm_r2_run, span);
}
static ftdm_status_t ftdm_r2_stop(ftdm_span_t *span)
{
ftdm_r2_data_t *r2_data = span->signal_data;
ftdm_clear_flag(r2_data, FTDM_R2_SPAN_STARTED);
while (ftdm_test_flag(r2_data, FTDM_R2_RUNNING)) {
ftdm_log(FTDM_LOG_DEBUG, "Waiting for R2 span %s\n", span->name);
ftdm_sleep(100);
@@ -444,6 +517,95 @@ static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_channel_sig_status)
return FTDM_SUCCESS;
}
static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_channel_sig_status)
{
openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan;
openr2_cas_signal_t rxcas, txcas;
/* get the current rx and tx cas bits */
openr2_chan_get_cas(r2chan, &rxcas, &txcas);
/* if we're already in the state the user asks us to be, we have nothing to do */
if (status == FTDM_SIG_STATE_SUSPENDED && txcas == OR2_CAS_BLOCK) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Channel signaling status already in BLOCK state\n");
return FTDM_SUCCESS;
}
if (status == FTDM_SIG_STATE_UP && txcas == OR2_CAS_IDLE) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Channel signaling status already in IDLE state\n");
return FTDM_SUCCESS;
}
/* set the signaling as requested and send SIGEVENT_SIGSTATUS_CHANGED, if applicable.
* see docs/sigstatus.txt for details */
switch(status) {
case FTDM_SIG_STATE_SUSPENDED:
openr2_chan_set_blocked(r2chan);
if (rxcas == OR2_CAS_IDLE) {
ftdm_r2_set_chan_sig_status(ftdmchan, status);
}
break;
case FTDM_SIG_STATE_UP:
openr2_chan_set_idle(r2chan);
if (rxcas == OR2_CAS_IDLE) {
ftdm_r2_set_chan_sig_status(ftdmchan, status);
}
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status);
return FTDM_FAIL;
}
return FTDM_SUCCESS;
}
static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_span_sig_status)
{
ftdm_iterator_t *citer = NULL;
ftdm_iterator_t *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;
}
/* if ALL channels are non-idle, report SUSPENDED. UP otherwise. */
*status = FTDM_SIG_STATE_SUSPENDED;
for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) {
ftdm_channel_t *fchan = ftdm_iterator_current(citer);
ftdm_channel_lock(fchan);
if (ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP)) {
*status = FTDM_SIG_STATE_UP;
ftdm_channel_unlock(fchan);
break;
}
ftdm_channel_unlock(fchan);
}
ftdm_iterator_free(chaniter);
return FTDM_SUCCESS;
}
static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_span_sig_status)
{
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *citer = NULL;
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;
}
/* iterate over all channels, setting them to the requested state */
for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) {
ftdm_channel_t *fchan = ftdm_iterator_current(citer);
/* we set channel's state through ftdm_r2_set_channel_sig_status(), since it already takes
* care of notifying the user when appropriate */
ftdm_channel_lock(fchan);
if ((ftdm_r2_set_channel_sig_status(fchan, status)) != FTDM_SUCCESS) {
ftdm_log_chan(fchan, FTDM_LOG_ERROR, "Failed to set signaling status to %s\n", ftdm_signaling_status2str(status));
}
ftdm_channel_unlock(fchan);
}
ftdm_iterator_free(chaniter);
return FTDM_SUCCESS;
}
/* always called from the monitor thread */
static void ftdm_r2_on_call_init(openr2_chan_t *r2chan)
{
@@ -510,13 +672,21 @@ static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, cons
ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Call offered with ANI = %s, DNIS = %s, Category = (%d)\n", ani, dnis, category);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
/* nothing went wrong during call setup, MF has ended, we can and must disable the MF dump */
if (r2data->mf_dump_size) {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_INPUT_DUMP, NULL);
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_OUTPUT_DUMP, NULL);
}
/* check if this is a collect call and if we should accept it */
if (!r2data->allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Rejecting collect call\n");
openr2_chan_disconnect_call(r2chan, OR2_CAUSE_COLLECT_CALL_REJECTED);
} else {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
}
ftdmchan->caller_data.cpc = ftdm_openr2_cpc_to_r2_ftdm_cpc(category);
}
/*
@@ -556,14 +726,14 @@ static void dump_mf(openr2_chan_t *r2chan)
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO output in prefix %s\n", logname);
snprintf(dfile, sizeof(dfile), logname ? "%s.s%dc%d.input.alaw" : "%s/s%dc%d.input.alaw",
logname ? logname : r2data->logdir, ftdmchan->span_id, ftdmchan->chan_id);
f = fopen(dfile, "w");
f = fopen(dfile, "wb");
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO input in file %s\n", dfile);
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_INPUT, f);
fclose(f);
snprintf(dfile, sizeof(dfile), logname ? "%s.s%dc%d.output.alaw" : "%s/s%dc%d.output.alaw",
logname ? logname : r2data->logdir, ftdmchan->span_id, ftdmchan->chan_id);
f = fopen(dfile, "w");
f = fopen(dfile, "wb");
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO output in file %s\n", dfile);
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_OUTPUT, f);
fclose(f);
@@ -573,6 +743,8 @@ static void dump_mf(openr2_chan_t *r2chan)
static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
{
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call accepted\n");
clear_accept_pending(ftdmchan);
@@ -595,6 +767,11 @@ static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t m
return;
}
} else {
/* nothing went wrong during call setup, MF has ended, we can and must disable the MF dump */
if (r2data->mf_dump_size) {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_INPUT_DUMP, NULL);
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_OUTPUT_DUMP, NULL);
}
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
}
}
@@ -653,7 +830,7 @@ static void ftdm_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf
static void ftdm_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
{
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Alarm notification: %d\n", alarm);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Alarm notification: %d\n", alarm);
}
static void ftdm_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
@@ -895,7 +1072,7 @@ static int ftdm_r2_io_write(openr2_chan_t *r2chan, const void *buf, int size)
if (FTDM_FAIL == status) {
return -1;
}
return outsize;
return (int)outsize;
}
static int ftdm_r2_io_read(openr2_chan_t *r2chan, const void *buf, int size)
@@ -906,7 +1083,7 @@ static int ftdm_r2_io_read(openr2_chan_t *r2chan, const void *buf, int size)
if (FTDM_FAIL == status) {
return -1;
}
return outsize;
return (int)outsize;
}
static int ftdm_r2_io_wait(openr2_chan_t *r2chan, int *flags, int block)
@@ -988,6 +1165,10 @@ static int ftdm_r2_io_get_oob_event(openr2_chan_t *r2chan, openr2_oob_event_t *e
return -1;
}
if (fevent->e_type != FTDM_EVENT_OOB) {
return 0;
}
switch (fevent->enum_id) {
case FTDM_OOB_CAS_BITS_CHANGE:
{
@@ -1396,13 +1577,14 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
span->sig_read = NULL;
span->sig_write = NULL;
/* let the core set the states, we just read them */
span->get_channel_sig_status = ftdm_r2_get_channel_sig_status;
span->signal_cb = sig_cb;
span->signal_type = FTDM_SIGTYPE_R2;
span->signal_data = r2data;
span->outgoing_call = r2_outgoing_call;
span->get_span_sig_status = ftdm_r2_get_span_sig_status;
span->set_span_sig_status = ftdm_r2_set_span_sig_status;
span->get_channel_sig_status = ftdm_r2_get_channel_sig_status;
span->set_channel_sig_status = ftdm_r2_set_channel_sig_status;
span->state_map = &r2_state_map;
@@ -1593,6 +1775,13 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
}
break;
/* INDICATE_RINGING doesn't apply to MFC/R2. maybe we could generate a tone */
case FTDM_CHANNEL_STATE_RINGING:
{
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RINGING indicated, ignoring it as it doesn't apply to MFC/R2\n");
}
break;
default:
{
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Unhandled channel state change: %s\n", ftdm_channel_state2str(ftdmchan->state));
@@ -1639,9 +1828,13 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
int index = 0;
struct timeval start, end;
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *citer = NULL;
uint32_t txqueue_size = 4;
short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count);
/* as long as this thread is running, this flag is set */
ftdm_set_flag(r2data, FTDM_R2_RUNNING);
#ifdef __linux__
r2data->monitor_thread_id = syscall(SYS_gettid);
#endif
@@ -1649,8 +1842,12 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
ftdm_log(FTDM_LOG_DEBUG, "OpenR2 monitor thread %lu started.\n", r2data->monitor_thread_id);
r2chan = NULL;
chaniter = ftdm_span_get_chan_iterator(span, NULL);
for (i = 1; chaniter; chaniter = ftdm_iterator_next(chaniter), i++) {
ftdmchan = ftdm_iterator_current(chaniter);
if (!chaniter) {
ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
goto done;
}
for (i = 1, citer = chaniter; citer; citer = ftdm_iterator_next(citer), i++) {
ftdmchan = ftdm_iterator_current(citer);
r2chan = R2CALL(ftdmchan)->r2chan;
openr2_chan_set_span_id(r2chan, span->span_id);
openr2_chan_set_idle(r2chan);
@@ -1660,7 +1857,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
memset(&start, 0, sizeof(start));
memset(&end, 0, sizeof(end));
while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_RUNNING)) {
while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_SPAN_STARTED)) {
res = gettimeofday(&end, NULL);
if (res) {
ftdm_log(FTDM_LOG_CRIT, "Failure gettimeofday [%s]\n", strerror(errno));
@@ -1685,24 +1882,24 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
/* deliver the actual channel events to the user now without any channel locking */
ftdm_span_trigger_signals(span);
#ifndef WIN32
/* figure out what event to poll each channel for. POLLPRI when the channel is down,
* POLLPRI|POLLIN|POLLOUT otherwise */
memset(poll_events, 0, sizeof(short)*span->chan_count);
chaniter = ftdm_span_get_chan_iterator(span, chaniter);
for (i = 0; chaniter; chaniter = ftdm_iterator_next(chaniter), i++) {
ftdmchan = ftdm_iterator_current(chaniter);
citer = ftdm_span_get_chan_iterator(span, chaniter);
if (!citer) {
ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
goto done;
}
for (i = 0; citer; citer = ftdm_iterator_next(citer), i++) {
ftdmchan = ftdm_iterator_current(citer);
r2chan = R2CALL(ftdmchan)->r2chan;
poll_events[i] = POLLPRI;
poll_events[i] = FTDM_EVENTS;
if (openr2_chan_get_read_enabled(r2chan)) {
poll_events[i] |= POLLIN;
poll_events[i] |= FTDM_READ;
}
}
status = ftdm_span_poll_event(span, waitms, poll_events);
#else
status = ftdm_span_poll_event(span, waitms, NULL);
#endif
/* run any span timers */
ftdm_sched_run(r2data->sched);
@@ -1732,9 +1929,9 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
/* this main loop takes care of MF and CAS signaling during call setup and tear down
* for every single channel in the span, do not perform blocking operations here! */
chaniter = ftdm_span_get_chan_iterator(span, chaniter);
for ( ; chaniter; chaniter = ftdm_iterator_next(chaniter)) {
ftdmchan = ftdm_iterator_current(chaniter);
citer = ftdm_span_get_chan_iterator(span, chaniter);
for ( ; citer; citer = ftdm_iterator_next(citer)) {
ftdmchan = ftdm_iterator_current(citer);
ftdm_mutex_lock(ftdmchan->mutex);
@@ -1761,10 +1958,11 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
ftdm_mutex_unlock(ftdmchan->mutex);
}
}
chaniter = ftdm_span_get_chan_iterator(span, chaniter);
for ( ; chaniter; chaniter = ftdm_iterator_next(chaniter)) {
ftdmchan = ftdm_iterator_current(chaniter);
done:
citer = ftdm_span_get_chan_iterator(span, chaniter);
for ( ; citer; citer = ftdm_iterator_next(citer)) {
ftdmchan = ftdm_iterator_current(citer);
r2chan = R2CALL(ftdmchan)->r2chan;
openr2_chan_set_blocked(r2chan);
}
@@ -1821,6 +2019,14 @@ static void __inline__ unblock_channel(ftdm_channel_t *fchan, ftdm_stream_handle
ftdm_mutex_unlock(fchan->mutex);
}
#define FT_SYNTAX "USAGE:\n" \
"--------------------------------------------------------------------------------\n" \
"ftdm r2 status <span_id|span_name>\n" \
"ftdm r2 loopstats <span_id|span_name>\n" \
"ftdm r2 block|unblock <span_id|span_name> [<chan_id>]\n" \
"ftdm r2 version\n" \
"ftdm r2 variants\n" \
"--------------------------------------------------------------------------------\n"
static FIO_API_FUNCTION(ftdm_r2_api)
{
ftdm_span_t *span = NULL;
@@ -1922,7 +2128,7 @@ static FIO_API_FUNCTION(ftdm_r2_api)
"Max DNIS: %d\n"
"ANI First: %s\n"
"Immediate Accept: %s\n"
"Job Thread: %lu\n"
"Job Thread: %u\n"
"Job Max ms: %d\n"
"Job Loops: %lu\n",
openr2_proto_get_variant_string(r2variant),
@@ -2004,14 +2210,6 @@ static FIO_API_FUNCTION(ftdm_r2_api)
}
if (argc == 1) {
if (!strcasecmp(argv[0], "threads")) {
ftdm_mutex_lock(g_thread_count_mutex);
stream->write_function(stream, "%d R2 channel threads up\n", g_thread_count);
ftdm_mutex_unlock(g_thread_count_mutex);
stream->write_function(stream, "+OK.\n");
goto done;
}
if (!strcasecmp(argv[0], "version")) {
stream->write_function(stream, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
stream->write_function(stream, "+OK.\n");
@@ -2037,7 +2235,7 @@ static FIO_API_FUNCTION(ftdm_r2_api)
}
}
stream->write_function(stream, "-ERR invalid command.\n");
stream->write_function(stream, "%s", FT_SYNTAX);
done:
@@ -2066,7 +2264,6 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_r2_init)
if (!g_mod_data_hash) {
return FTDM_FAIL;
}
ftdm_mutex_create(&g_thread_count_mutex);
return FTDM_SUCCESS;
}
@@ -2086,7 +2283,6 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_r2_destroy)
}
}
hashtable_destroy(g_mod_data_hash);
ftdm_mutex_destroy(&g_thread_count_mutex);
return FTDM_SUCCESS;
}
@@ -839,7 +839,7 @@ static void handle_call_released(ftdm_span_t *span, sangomabc_connection_t *mcon
if ((ftdmchan = find_ftdmchan(span, event, 1))) {
ftdm_log(FTDM_LOG_DEBUG, "Releasing completely chan s%dc%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event),
BOOST_EVENT_CHAN(mcon->sigmod, event));
ftdm_channel_done(ftdmchan);
ftdm_channel_close(&ftdmchan);
} else {
ftdm_log(FTDM_LOG_CRIT, "Odd, We could not find chan: s%dc%d to release the call completely!!\n",
BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
@@ -1105,8 +1105,9 @@ static void handle_call_loop_start(ftdm_span_t *span, sangomabc_connection_t *mc
ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP, res);
if (res != FTDM_SUCCESS) {
ftdm_channel_t *toclose = ftdmchan;
ftdm_log(FTDM_LOG_CRIT, "yay, could not set the state of the channel to IN_LOOP, loop will fail\n");
ftdm_channel_done(ftdmchan);
ftdm_channel_close(&toclose);
return;
}
ftdm_log(FTDM_LOG_DEBUG, "%d:%d starting loop\n", ftdmchan->span_id, ftdmchan->chan_id);
@@ -1426,11 +1427,12 @@ static __inline__ ftdm_status_t state_advance(ftdm_channel_t *ftdmchan)
ftdmchan->sflags = 0;
memset(ftdmchan->call_data, 0, sizeof(sangoma_boost_call_t));
if (sangoma_boost_data->sigmod && call_stopped_ack_sent) {
/* we dont want to call ftdm_channel_done just yet until call released is received */
/* we dont want to call ftdm_channel_close just yet until call released is received */
ftdm_log(FTDM_LOG_DEBUG, "Waiting for call release confirmation before declaring chan %d:%d as available \n",
ftdmchan->span_id, ftdmchan->chan_id);
} else {
ftdm_channel_done(ftdmchan);
ftdm_channel_t *toclose = ftdmchan;
ftdm_channel_close(&toclose);
}
}
break;
@@ -2476,7 +2478,7 @@ static BOOST_SIG_STATUS_CB_FUNCTION(ftdm_boost_sig_status_change)
sig.span_id = ftdmchan->span_id;
sig.channel = ftdmchan;
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sig.raw_data = &status;
sig.ev_data.sigstatus.status = status;
ftdm_span_send_signal(ftdmchan->span, &sig);
return;
}
@@ -31,6 +31,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define _GNU_SOURCE
#if HAVE_NETDB_H
#include <netdb.h>
#endif
@@ -65,7 +65,13 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_ANY_STATE, FTDM_END},
{FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END}
{FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_RESTART, FTDM_END}
},
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_RESET, FTDM_END},
{FTDM_CHANNEL_STATE_DOWN, FTDM_END}
},
{
ZSD_INBOUND,
@@ -170,7 +176,13 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_ANY_STATE, FTDM_END},
{FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
{FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_RESET, FTDM_END},
{FTDM_CHANNEL_STATE_DOWN, FTDM_END}
},
{
ZSD_OUTBOUND,
@@ -203,7 +215,7 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_DIALING, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
FTDM_CHANNEL_STATE_DOWN, FTDM_END}
},
{
@@ -211,14 +223,20 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_PROCEED, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_RINGING, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
@@ -626,8 +644,11 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
case FTDM_CHANNEL_STATE_GET_CALLERID:
{
if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
/* By default, we do not send a progress indicator in the proceed */
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};
sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
sngisdn_snd_proceed(ftdmchan);
sngisdn_snd_proceed(ftdmchan, prog_ind);
}
/* Wait in this state until we get FACILITY msg */
}
@@ -666,16 +687,28 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
ftdm_span_send_signal(ftdmchan->span, &sigev);
} else {
if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
/* By default, we do not send a progress indicator in the proceed */
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};
sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
sngisdn_snd_proceed(ftdmchan);
sngisdn_snd_proceed(ftdmchan, prog_ind);
}
}
}
break;
case FTDM_CHANNEL_STATE_RINGING:
{
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
sngisdn_snd_alert(ftdmchan, prog_ind);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
/* OUTBOUND...so we were told by the line of this so notify the user */
sigev.event_id = FTDM_SIGEVENT_RINGING;
ftdm_span_send_signal(ftdmchan->span, &sigev);
if (sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY)) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
}
} else {
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
sngisdn_snd_alert(ftdmchan, prog_ind);
}
}
break;
case FTDM_CHANNEL_STATE_PROGRESS:
@@ -686,12 +719,9 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
sigev.event_id = FTDM_SIGEVENT_PROGRESS;
ftdm_span_send_signal(ftdmchan->span, &sigev);
} else {
/* If we already sent a PROCEED before, do not send a PROGRESS as there is nothing to indicate to the remote switch */
if (ftdmchan->last_state != FTDM_CHANNEL_STATE_PROCEED) {
/* Send a progress message, indicating: Call is not end-to-end ISDN, further call progress may be available */
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
sngisdn_snd_progress(ftdmchan, prog_ind);
}
/* Send a progress message, indicating: Call is not end-to-end ISDN, further call progress may be available */
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
sngisdn_snd_progress(ftdmchan, prog_ind);
}
}
break;
@@ -774,7 +804,7 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
sngisdn_snd_release(ftdmchan, 0);
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
sngisdn_set_span_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
}
} else {
sngisdn_snd_disconnect(ftdmchan);
@@ -832,6 +862,11 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
/* IMPLEMENT ME */
}
break;
case FTDM_CHANNEL_STATE_RESET:
{
sngisdn_snd_restart(ftdmchan);
}
break;
default:
{
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "unsupported sngisdn_rcvd state %s\n", ftdm_channel_state2str(ftdmchan->state));
@@ -851,6 +886,22 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
return;
}
static FIO_CHANNEL_SEND_MSG_FUNCTION(ftdm_sangoma_isdn_send_msg)
{
ftdm_status_t status = FTDM_FAIL;
switch (sigmsg->event_id) {
case FTDM_SIGEVENT_FACILITY:
sngisdn_snd_fac_req(ftdmchan);
break;
default:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Unsupported signalling msg requested\n");
status = FTDM_BREAK;
}
ftdm_call_clear_data(&ftdmchan->caller_data);
return status;
}
static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_isdn_outgoing_call)
{
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
@@ -925,7 +976,8 @@ 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)
{
{
sngisdn_span_data_t *signal_data = span->signal_data;
ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id);
if (sngisdn_stack_start(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name);
@@ -935,6 +987,14 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
if (signal_data->raw_trace_q921 == SNGISDN_OPT_TRUE) {
sngisdn_activate_trace(span, SNGISDN_TRACE_Q921);
}
if (signal_data->raw_trace_q931 == SNGISDN_OPT_TRUE) {
sngisdn_activate_trace(span, SNGISDN_TRACE_Q931);
}
/*start the span monitor thread*/
if (ftdm_thread_create_detached(ftdm_sangoma_isdn_run, span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT,"Failed to start Sangoma ISDN Span Monitor Thread!\n");
@@ -1030,6 +1090,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
span->stop = ftdm_sangoma_isdn_stop;
span->signal_type = FTDM_SIGTYPE_ISDN;
span->outgoing_call = ftdm_sangoma_isdn_outgoing_call;
span->send_msg = ftdm_sangoma_isdn_send_msg;
span->channel_request = NULL;
span->signal_cb = sig_cb;
span->get_channel_sig_status = ftdm_sangoma_isdn_get_chan_sig_status;
@@ -1040,11 +1101,12 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE);
ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE);
ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE);
ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES);
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
span->trunk_type == FTDM_TRUNK_BRI) {
sngisdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
sngisdn_set_span_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
}
/* Initialize scheduling context */
@@ -1139,6 +1201,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
goto done;
}
/* TODO: Move functions to table + function pointers */
if (!strcasecmp(argv[0], "trace")) {
char *trace_opt;
@@ -1156,6 +1219,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
stream->write_function(stream, "-ERR failed to find span by name %s\n", argv[2]);
goto done;
}
if (!strcasecmp(trace_opt, "q921")) {
sngisdn_activate_trace(span, SNGISDN_TRACE_Q921);
} else if (!strcasecmp(trace_opt, "q931")) {
@@ -1164,7 +1228,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
sngisdn_activate_trace(span, SNGISDN_TRACE_DISABLE);
} else {
stream->write_function(stream, "-ERR invalid trace option <q921|q931> <span name>\n");
}
}
}
if (!strcasecmp(argv[0], "l1_stats")) {
ftdm_span_t *span;
@@ -1182,7 +1246,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
}
sngisdn_print_phy_stats(stream, span);
}
if (!strcasecmp(argv[0], "show_spans")) {
ftdm_span_t *span = NULL;
if (argc == 2) {
@@ -101,9 +101,11 @@ typedef enum {
FLAG_GLARE = (1 << 6),
FLAG_DELAYED_REL = (1 << 7),
FLAG_SENT_PROCEED = (1 << 8),
FLAG_SEND_DISC = (1 << 9),
FLAG_SEND_DISC = (1 << 9),
/* Used for BRI only, flag is set after we request line CONNECTED */
FLAG_ACTIVATING = (1 << 10),
FLAG_ACTIVATING = (1 << 10),
/* Used when we receive an ALERT msg + inband tones ready */
FLAG_MEDIA_READY = (1 << 11),
} sngisdn_flag_t;
@@ -259,6 +261,8 @@ typedef struct sngisdn_span_data {
int8_t facility_timeout;
uint8_t num_local_numbers;
uint8_t ignore_cause_value;
uint8_t raw_trace_q931;
uint8_t raw_trace_q921;
uint8_t timer_t3;
uint8_t restart_opt;
char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
@@ -352,8 +356,11 @@ void clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info);
ftdm_status_t get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data);
ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data);
ftdm_status_t sngisdn_set_span_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail);
ftdm_status_t sngisdn_set_chan_avail_rate(ftdm_channel_t *chan, sngisdn_avail_t avail);
void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status);
void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status);
ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail);
ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
@@ -363,7 +370,7 @@ void stack_pst_init(Pst *pst);
/* Outbound Call Control functions */
void sngisdn_snd_setup(ftdm_channel_t *ftdmchan);
void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan);
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan);
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
void sngisdn_snd_connect(ftdm_channel_t *ftdmchan);
@@ -374,6 +381,7 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan);
void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan);
void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan);
void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan);
void sngisdn_snd_restart(ftdm_channel_t *ftdmchan);
void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len);
void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event);
@@ -421,8 +429,11 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event);
void sngisdn_rcv_phy_ind(SuId suId, Reason reason);
void sngisdn_rcv_q921_ind(BdMngmt *status);
void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
void sngisdn_trace_interpreted_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
void get_memory_info(void);
ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
@@ -436,6 +447,7 @@ void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...);
void sngisdn_rcv_sng_assert(char *message);
ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb);
ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb);
ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *display);
@@ -443,16 +455,20 @@ ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *us
ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd);
ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t data_len);
ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t data_len);
ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb);
ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb);
ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt);
ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind);
ftdm_status_t set_bear_cap_ie(ftdm_channel_t *ftdmchan, BearCap *bearCap);
ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId);
ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd);
ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t *data_len);
ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len);
uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability);
@@ -480,7 +496,6 @@ static __inline__ void sngisdn_set_flag(sngisdn_chan_data_t *sngisdn_info, sngis
void handle_sng_log(uint8_t level, char *fmt,...);
void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status);
void sngisdn_delayed_setup(void* p_sngisdn_info);
void sngisdn_delayed_release(void* p_sngisdn_info);
void sngisdn_delayed_connect(void* p_sngisdn_info);
@@ -296,6 +296,10 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
parse_yesno(var, val, &signal_data->facility_ie_decode);
} else if (!strcasecmp(var, "ignore-cause-value")) {
parse_yesno(var, val, &signal_data->ignore_cause_value);
} else if (!strcasecmp(var, "q931-raw-trace")) {
parse_yesno(var, val, &signal_data->raw_trace_q931);
} else if (!strcasecmp(var, "q921-raw-trace")) {
parse_yesno(var, val, &signal_data->raw_trace_q921);
} else {
ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
}
@@ -47,7 +47,7 @@ void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status
sig.span_id = ftdmchan->span_id;
sig.channel = ftdmchan;
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sig.sigstatus = status;
sig.ev_data.sigstatus.status = status;
ftdm_span_send_signal(ftdmchan->span, &sig);
return;
}
@@ -33,7 +33,8 @@
*/
#include "ftmod_sangoma_isdn.h"
ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn);
static ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn);
static void sngisdn_process_restart_confirm(ftdm_channel_t *ftdmchan);
/* Remote side transmit a SETUP */
void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
@@ -123,12 +124,9 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
break;
}
#if 0
/* Export ftdmchan variables here if we need to */
ftdm_channel_add_var(ftdmchan, "isdn_specific_var", "1");
#endif
/* Fill in call information */
get_calling_num(ftdmchan, &conEvnt->cgPtyNmb);
get_calling_num2(ftdmchan, &conEvnt->cgPtyNmb2);
get_called_num(ftdmchan, &conEvnt->cdPtyNmb);
get_redir_num(ftdmchan, &conEvnt->redirNmb);
get_calling_subaddr(ftdmchan, &conEvnt->cgPtySad);
@@ -235,6 +233,9 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
}
break;
case FTDM_CHANNEL_STATE_RESET:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing SETUP in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
break;
@@ -277,6 +278,7 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_RINGING:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_DIALING:
@@ -288,6 +290,9 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_HANGUP:
/* Race condition, we just hung up the call - ignore this message */
break;
case FTDM_CHANNEL_STATE_RESET:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
@@ -304,6 +309,9 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* Race condition, We just hung up an incoming call right after we sent a CONNECT - ignore this message */
break;
case FTDM_CHANNEL_STATE_RESET:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
@@ -357,27 +365,47 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
goto sngisdn_process_cnst_ind_end;
}
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_DIALING:
case FTDM_CHANNEL_STATE_PROCEED:
if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} else if (evntType == MI_CALLPROC) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED);
} else {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_RINGING:
if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
sngisdn_set_flag(sngisdn_info, FLAG_MEDIA_READY);
}
switch (evntType) {
case MI_CALLPROC:
if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED);
}
break;
case MI_ALERTING:
if (ftdmchan->state == FTDM_CHANNEL_STATE_PROCEED) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RINGING);
}
break;
case MI_PROGRESS:
if (sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY)) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} else if (ftdmchan->state != FTDM_CHANNEL_STATE_PROGRESS) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
}
break;
default:
/* We should never reach this section !*/
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle this event %d\n", evntType);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
/* We are already in progress media, we can't go to any higher state except up */
/* Do nothing */
break;
case FTDM_CHANNEL_STATE_RESET:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing ALERT/PROCEED/PROGRESS in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
@@ -410,12 +438,16 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
}
break;
case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_RINGING:
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_UP:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Receiving more digits %s, but we already proceeded with call\n", cnStEvnt->cdPtyNmb.nmbDigits.val);
break;
case FTDM_CHANNEL_STATE_RESET:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "\n", suId, suInstId, spInstId);
break;
@@ -450,6 +482,7 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_RINGING:
case FTDM_CHANNEL_STATE_DIALING:
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
@@ -478,6 +511,9 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event)
/* This is a race condition. We just sent a DISCONNECT, on this channel */
/* Do nothing */
break;
case FTDM_CHANNEL_STATE_RESET:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
@@ -532,7 +568,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_DIALING:
/* Remote side rejected our SETUP message on outbound call */
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
sngisdn_set_span_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
}
/* fall-through */
case FTDM_CHANNEL_STATE_PROCEED:
@@ -540,6 +576,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_UP:
case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_RINGING:
/* If we previously had a glare on this channel,
this RELEASE could be for the previous call. Confirm whether call_data has
not changed while we were waiting for ftdmchan->mutex by comparing suInstId's */
@@ -581,6 +618,9 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
/* set abort flag so that we do not transmit another release complete on this channel once FS core is done */
}
break;
case FTDM_CHANNEL_STATE_RESET:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RELEASE in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
@@ -757,14 +797,14 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
{
ftdm_sigmsg_t sigev;
if (facEvnt->facElmt.facStr.pres) {
get_facility_ie_str(ftdmchan, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len);
get_facility_ie_str(ftdmchan, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len-2);
}
memset(&sigev, 0, sizeof(sigev));
sigev.chan_id = ftdmchan->chan_id;
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
sigev.event_id = FTDM_SIGEVENT_MSG;
sigev.event_id = FTDM_SIGEVENT_FACILITY;
ftdm_span_send_signal(ftdmchan->span, &sigev);
}
break;
@@ -884,6 +924,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
break;
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_RINGING:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Remote switch expecting OVERLAP receive, but we are already PROCEEDING\n");
sngisdn_snd_disconnect(ftdmchan);
@@ -902,6 +943,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_RINGING:
/* T310 timer has expired */
ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T310 Timer expired, hanging up call\n");
@@ -938,6 +980,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
break;
case 9: /* Remote switch is in "Incoming call proceeding" state */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_RINGING:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_GET_CALLERID:
@@ -1047,18 +1090,91 @@ void sngisdn_process_srv_cfm (sngisdn_event_data_t *sngisdn_event)
return;
}
static void sngisdn_process_restart_confirm(ftdm_channel_t *ftdmchan)
{
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_RESET:
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
break;
case FTDM_CHANNEL_STATE_DOWN:
/* Do nothing */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RESTART CFM in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
}
return;
}
void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
{
int16_t suId = sngisdn_event->suId;
int16_t dChan = sngisdn_event->dChan;
uint8_t ces = sngisdn_event->ces;
uint8_t evntType = sngisdn_event->evntType;
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
/* Function does not require any info from ssHlEvnt struct for now */
/*Rst *rstEvnt = &sngisdn_event->event.rstEvnt;*/
uint8_t chan_no = 0;
Rst *rstEvnt = &sngisdn_event->event.rstEvnt;
sngisdn_span_data_t *signal_data = g_sngisdn_data.dchans[dChan].spans[1];
if (!signal_data) {
ftdm_log(FTDM_LOG_CRIT, "Received RESTART on unconfigured span (suId:%d)\n", suId);
return;
}
if (!rstEvnt->rstInd.eh.pres || !rstEvnt->rstInd.rstClass.pres) {
ftdm_log(FTDM_LOG_DEBUG, "Receved RESTART, but Restart Indicator IE not present\n");
return;
}
switch(rstEvnt->rstInd.rstClass.val) {
case IN_CL_INDCHAN: /* Indicated b-channel */
if (rstEvnt->chanId.eh.pres) {
if (rstEvnt->chanId.intType.val == IN_IT_BASIC) {
if (rstEvnt->chanId.infoChanSel.pres == PRSNT_NODEF) {
chan_no = rstEvnt->chanId.infoChanSel.val;
}
} else if (rstEvnt->chanId.intType.val == IN_IT_OTHER) {
if (rstEvnt->chanId.chanNmbSlotMap.pres == PRSNT_NODEF) {
chan_no = rstEvnt->chanId.chanNmbSlotMap.val[0];
}
}
}
if (!chan_no) {
ftdm_log(FTDM_LOG_CRIT, "Failed to determine channel from RESTART\n");
return;
}
break;
case IN_CL_SNGINT: /* Single interface */
case IN_CL_ALLINT: /* All interfaces */
/* In case restart class indicates all interfaces, we will duplicate
this event on each span associated to this d-channel in sngisdn_rcv_rst_cfm,
so treat it as a single interface anyway */
break;
default:
ftdm_log(FTDM_LOG_CRIT, "Invalid restart indicator class:%d\n", rstEvnt->rstInd.rstClass.val);
return;
}
if (chan_no) { /* For a single channel */
if (chan_no > ftdm_span_get_chan_count(signal_data->ftdm_span)) {
ftdm_log(FTDM_LOG_CRIT, "Received RESTART on invalid channel:%d\n", chan_no);
} else {
ftdm_channel_t *ftdmchan = ftdm_span_get_channel(signal_data->ftdm_span, chan_no);
sngisdn_process_restart_confirm(ftdmchan);
}
} else { /* for all channels */
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
sngisdn_process_restart_confirm((ftdm_channel_t*)ftdm_iterator_current(curr));
}
ftdm_iterator_free(chaniter);
}
ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d type:%d)\n", suId, dChan, ces, evntType);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
@@ -1087,7 +1203,7 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
return;
}
ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn)
static ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
@@ -51,72 +51,6 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
ftdm_mutex_unlock(g_sngisdn_data.ccs[signal_data->cc_id].mutex);
memset(&conEvnt, 0, sizeof(conEvnt));
conEvnt.bearCap[0].eh.pres = PRSNT_NODEF;
conEvnt.bearCap[0].infoTranCap.pres = PRSNT_NODEF;
conEvnt.bearCap[0].infoTranCap.val = sngisdn_get_infoTranCap_from_user(ftdmchan->caller_data.bearer_capability);
conEvnt.bearCap[0].codeStand0.pres = PRSNT_NODEF;
conEvnt.bearCap[0].codeStand0.val = IN_CSTD_CCITT;
conEvnt.bearCap[0].infoTranRate0.pres = PRSNT_NODEF;
conEvnt.bearCap[0].infoTranRate0.val = IN_ITR_64KBIT;
conEvnt.bearCap[0].tranMode.pres = PRSNT_NODEF;
conEvnt.bearCap[0].tranMode.val = IN_TM_CIRCUIT;
conEvnt.chanId.eh.pres = PRSNT_NODEF;
conEvnt.chanId.prefExc.pres = PRSNT_NODEF;
conEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
conEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
conEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
conEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
conEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
conEvnt.chanId.intIdent.pres = NOTPRSNT;
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
/* Trillium stack rejests lyr1Ident on BRI, but Netbricks always sends it.
Check with Trillium if this ever causes calls to fail in the field */
/* BRI only params */
conEvnt.chanId.intType.pres = PRSNT_NODEF;
conEvnt.chanId.intType.val = IN_IT_BASIC;
conEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
conEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
} else {
/* PRI only params */
conEvnt.bearCap[0].usrInfoLyr1Prot.pres = PRSNT_NODEF;
conEvnt.bearCap[0].usrInfoLyr1Prot.val = sngisdn_get_usrInfoLyr1Prot_from_user(ftdmchan->caller_data.bearer_layer1);
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN &&
conEvnt.bearCap[0].usrInfoLyr1Prot.val == IN_UIL1_G711ULAW) {
/* We are bridging a call from T1 */
conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
} else if (conEvnt.bearCap[0].usrInfoLyr1Prot.val == IN_UIL1_G711ALAW) {
/* We are bridging a call from E1 */
conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
}
conEvnt.bearCap[0].lyr1Ident.pres = PRSNT_NODEF;
conEvnt.bearCap[0].lyr1Ident.val = IN_L1_IDENT;
conEvnt.chanId.intType.pres = PRSNT_NODEF;
conEvnt.chanId.intType.val = IN_IT_OTHER;
conEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
conEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
conEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
conEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
conEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
conEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
conEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
conEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
conEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
conEvnt.chanId.chanNmbSlotMap.len = 1;
conEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) {
conEvnt.sndCmplt.eh.pres = PRSNT_NODEF;
}
@@ -126,8 +60,11 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Outgoing call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits);
set_chan_id_ie(ftdmchan, &conEvnt.chanId);
set_bear_cap_ie(ftdmchan, &conEvnt.bearCap[0]);
set_called_num(ftdmchan, &conEvnt.cdPtyNmb);
set_calling_num(ftdmchan, &conEvnt.cgPtyNmb);
set_calling_num2(ftdmchan, &conEvnt.cgPtyNmb2);
set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad);
set_redir_num(ftdmchan, &conEvnt.redirNmb);
set_calling_name(ftdmchan, &conEvnt);
@@ -160,38 +97,7 @@ void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan)
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
/* BRI only params */
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
} else {
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP ACK (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
@@ -220,38 +126,7 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
/* BRI only params */
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
} else {
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
set_chan_id_ie(ftdmchan, &cnStEvnt.chanId);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT COMPL (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
@@ -262,10 +137,9 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
}
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind)
{
CnStEvnt cnStEvnt;
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
@@ -277,40 +151,12 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
}
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
/* BRI only params */
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
} else {
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
set_chan_id_ie(ftdmchan, &cnStEvnt.chanId);
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROCEED (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
@@ -343,6 +189,7 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, signal_data->dchan_id, sngisdn_info->ces)) {
@@ -369,6 +216,7 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
@@ -393,41 +241,11 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
}
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
/* BRI only params */
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
} else {
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
set_chan_id_ie(ftdmchan, &cnStEvnt.chanId);
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_con_response(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
@@ -450,10 +268,17 @@ void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan)
memset(&facEvnt, 0, sizeof(facEvnt));
set_facility_ie_str(ftdmchan, &facEvnt.facElmt.facStr.val[2], (ftdm_size_t*)&facEvnt.facElmt.facStr.len);
if (set_facility_ie_str(ftdmchan, &facEvnt.facElmt.facStr.val[2], (uint8_t*)&facEvnt.facElmt.facStr.len) != FTDM_SUCCESS) {
/* No point in sending a FACILITY message if there is no Facility IE to transmit */
return;
}
ftdm_call_clear_data(&ftdmchan->caller_data);
facEvnt.facElmt.eh.pres = PRSNT_NODEF;
facEvnt.facElmt.facStr.pres = PRSNT_NODEF;
facEvnt.facElmt.facStr.val[0] = 0x1C;
facEvnt.facElmt.facStr.val[1] = facEvnt.facElmt.facStr.len;
facEvnt.facElmt.facStr.val[1] = (uint8_t)facEvnt.facElmt.facStr.len;
facEvnt.facElmt.facStr.len +=2; /* Need to include the size of identifier + len */
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending FACILITY (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
@@ -481,6 +306,8 @@ void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan)
//ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ\n");
ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_con_status(signal_data->cc_id, 0, 0, &cnStEvnt, MI_INFO, signal_data->dchan_id, sngisdn_info->ces)) {
@@ -501,6 +328,8 @@ void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan)
memset(&staEvnt, 0, sizeof(StaEvnt));
ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Status ENQ on suId:%d suInstId:%u spInstId:%d dchan:%d ces:%d\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_status_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &staEvnt, MI_STATENQ)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused Status ENQ request\n");
@@ -539,6 +368,7 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT;
set_facility_ie(ftdmchan, &discEvnt.facilityStr);
ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) {
@@ -546,6 +376,7 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
}
return;
}
void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
{
RelEvnt relEvnt;
@@ -585,6 +416,7 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
}
set_facility_ie(ftdmchan, &relEvnt.facilityStr);
ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, suInstId, spInstId);
@@ -600,6 +432,24 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
return;
}
void sngisdn_snd_restart(ftdm_channel_t *ftdmchan)
{
Rst rstEvnt;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
memset(&rstEvnt, 0, sizeof(rstEvnt));
set_chan_id_ie(ftdmchan, &rstEvnt.chanId);
set_restart_ind_ie(ftdmchan, &rstEvnt.rstInd);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RESTART (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, signal_data->dchan_id, CES_MNGMNT);
if (sng_isdn_restart_request(signal_data->cc_id, &rstEvnt, signal_data->dchan_id, CES_MNGMNT, IN_SND_RST)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused RESTART request\n");
}
return;
}
/* We received an incoming frame on the d-channel, send data to the stack */
void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len)
@@ -34,9 +34,6 @@
#include "ftmod_sangoma_isdn.h"
#define MAX_DECODE_STR_LEN 2000
void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces)
{
uint8_t bchan_no = 0;
@@ -630,8 +627,9 @@ void sngisdn_rcv_rst_cfm (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType);
/* Enqueue the event to each span within the dChan */
for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
signal_data = g_sngisdn_data.dchans[dChan].spans[i];
@@ -725,14 +723,25 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
ftdmspan = signal_data->ftdm_span;
if (status->t.usta.alarm.event == LCM_EVENT_UP) {
uint32_t chan_no = status->t.usta.evntParm[2];
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
status->t.usta.suId,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_UP);
sngisdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_UP);
if (chan_no) {
ftdm_channel_t *ftdmchan = ftdm_span_get_channel(ftdmspan, chan_no);
if (ftdmchan) {
sngisdn_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
sngisdn_set_chan_avail_rate(ftdmchan, SNGISDN_AVAIL_UP);
} else {
ftdm_log(FTDM_LOG_CRIT, "stack alarm event on invalid channel :%d\n", chan_no);
}
} else {
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_UP);
sngisdn_set_span_avail_rate(ftdmspan, SNGISDN_AVAIL_UP);
}
} else {
ftdm_log(FTDM_LOG_WARNING, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
status->t.usta.suId,
@@ -741,7 +750,7 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_DOWN);
sngisdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
sngisdn_set_span_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
}
}
break;
@@ -765,9 +774,6 @@ void sngisdn_rcv_cc_ind(CcMngmt *status)
return;
}
#define Q931_TRC_EVENT(event) (event == TL3PKTTX)?"TX": \
(event == TL3PKTRX)?"RX":"UNKNOWN"
void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
{
MsgLen mlen;
@@ -776,13 +782,20 @@ void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
Buffer *tmp;
Data *cptr;
uint8_t data;
ftdm_trace_dir_t dir;
uint8_t tdata[1000];
char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[trc->t.trc.suId];
ftdm_assert(mBuf != NULLP, "Received a Q931 trace with no buffer");
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
if (mlen != 0) {
if (trc->t.trc.evnt == TL3PKTTX) {
dir = FTDM_TRACE_OUTGOING;
} else {
dir = FTDM_TRACE_INCOMING;
}
if (mlen) {
tmp = mBuf->b_cont;
cptr = tmp->b_rptr;
data = *cptr++;
@@ -797,41 +810,40 @@ void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
}
data = *cptr++;
}
sngisdn_trace_q931(data_str, tdata, mlen);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d FRAME %s:%s\n", trc->t.trc.suId, Q931_TRC_EVENT(trc->t.trc.evnt), data_str);
if (signal_data->raw_trace_q931 == SNGISDN_OPT_TRUE) {
sngisdn_trace_raw_q931(signal_data, dir, tdata, mlen);
} else {
sngisdn_trace_interpreted_q931(signal_data, dir, tdata, mlen);
}
}
ftdm_safe_free(data_str);
/* We do not need to free mBuf in this case because stack does it */
/* SPutMsg(mBuf); */
return;
}
#define Q921_TRC_EVENT(event) (event == TL2FRMRX)?"RX": \
(event == TL2FRMTX)?"TX": \
(event == TL2TMR)?"TMR EXPIRED":"UNKNOWN"
void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
{
MsgLen mlen;
Buffer *tmp;
MsgLen i;
int16_t j;
Buffer *tmp;
Data *cptr;
uint8_t data;
uint8_t tdata[16];
char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
ftdm_trace_dir_t dir;
uint8_t tdata[1000];
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[trc->t.trc.lnkNmb];
if (trc->t.trc.evnt == TL2TMR) {
goto end_of_trace;
return;
}
if (trc->t.trc.evnt == TL2FRMTX) {
dir = FTDM_TRACE_OUTGOING;
} else {
dir = FTDM_TRACE_INCOMING;
}
ftdm_assert(mBuf != NULLP, "Received a Q921 trace with no buffer");
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
if (mlen != 0) {
tmp = mBuf->b_cont;
cptr = tmp->b_rptr;
@@ -853,12 +865,12 @@ void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
}
}
sngisdn_trace_q921(data_str, tdata, mlen);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] s%d FRAME %s:%s\n", trc->t.trc.lnkNmb, Q921_TRC_EVENT(trc->t.trc.evnt), data_str);
if (signal_data->raw_trace_q921 == SNGISDN_OPT_TRUE) {
sngisdn_trace_raw_q921(signal_data, dir, tdata, mlen);
} else {
sngisdn_trace_interpreted_q921(signal_data, dir, tdata, mlen);
}
}
end_of_trace:
ftdm_safe_free(data_str);
SPutMsg(mBuf);
return;
}
@@ -136,19 +136,25 @@ ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn
return FTDM_SUCCESS;
}
ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail)
ftdm_status_t sngisdn_set_chan_avail_rate(ftdm_channel_t *chan, sngisdn_avail_t avail)
{
if (span->trunk_type == FTDM_TRUNK_BRI ||
span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
if (FTDM_SPAN_IS_BRI(chan->span)) {
ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Setting availability rate to:%d\n", avail);
chan->availability_rate = avail;
}
return FTDM_SUCCESS;
}
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);
((ftdm_channel_t*)ftdm_iterator_current(curr))->availability_rate = avail;
sngisdn_set_chan_avail_rate(((ftdm_channel_t*)ftdm_iterator_current(curr)), avail);
}
ftdm_iterator_free(chaniter);
}
@@ -185,6 +191,39 @@ ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
return FTDM_SUCCESS;
}
ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (cgPtyNmb->eh.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
if (cgPtyNmb->screenInd.pres == PRSNT_NODEF) {
ftdm_call_add_var(caller_data, "isdn.cg_pty2.screen_ind", ftdm_screening2str(cgPtyNmb->screenInd.val));
}
if (cgPtyNmb->presInd0.pres == PRSNT_NODEF) {
ftdm_call_add_var(caller_data, "isdn.cg_pty2.presentation_ind", ftdm_presentation2str(cgPtyNmb->presInd0.val));
}
if (cgPtyNmb->nmbPlanId.pres == PRSNT_NODEF) {
ftdm_call_add_var(caller_data, "isdn.cg_pty2.npi", ftdm_npi2str(cgPtyNmb->nmbPlanId.val));
}
if (cgPtyNmb->typeNmb1.pres == PRSNT_NODEF) {
ftdm_call_add_var(caller_data, "isdn.cg_pty2.ton", ftdm_ton2str(cgPtyNmb->typeNmb1.val));
}
if (cgPtyNmb->nmbDigits.pres == PRSNT_NODEF) {
char digits_string [32];
memcpy(digits_string, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len);
digits_string[cgPtyNmb->nmbDigits.len] = '\0';
ftdm_call_add_var(caller_data, "isdn.cg_pty2.digits", digits_string);
}
memcpy(&caller_data->ani, &caller_data->cid_num, sizeof(caller_data->ani));
return FTDM_SUCCESS;
}
ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
@@ -278,7 +317,7 @@ ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
memcpy(subaddress, (char*)cgPtySad->sadInfo.val, cgPtySad->sadInfo.len);
subaddress[cgPtySad->sadInfo.len] = '\0';
ftdm_channel_add_var(ftdmchan, "isdn.calling_subaddr", subaddress);
ftdm_call_add_var(&ftdmchan->caller_data, "isdn.calling_subaddr", subaddress);
return FTDM_SUCCESS;
}
@@ -291,17 +330,16 @@ ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr
return get_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, facilityStr->facilityStr.len);
}
ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t data_len)
ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t data_len)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) {
if (data_len > sizeof(caller_data->raw_data)-2) {
ftdm_log(FTDM_LOG_CRIT, "Length of Facility IE exceeds maximum length\n");
return FTDM_FAIL;
}
/* size of facilityStr->facilityStr.len is a uint8_t so no need to check
for overflow here as facilityStr->facilityStr.len will always be smaller
than sizeof(caller_data->raw_data) */
memset(caller_data->raw_data, 0, sizeof(caller_data->raw_data));
/* Always include Facility IE identifier + len so this can be used as a sanity check by the user */
caller_data->raw_data[0] = SNGISDN_Q931_FACILITY_IE_ID;
@@ -348,7 +386,7 @@ ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd)
val = SNGISDN_PROGIND_DESCR_INVALID;
break;
}
ftdm_channel_add_var(ftdmchan, "isdn.prog_ind.descr", ftdm_sngisdn_progind_descr2str(val));
ftdm_call_add_var(&ftdmchan->caller_data, "isdn.prog_ind.descr", ftdm_sngisdn_progind_descr2str(val));
}
if (progInd->location.pres) {
@@ -379,7 +417,7 @@ ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd)
val = SNGISDN_PROGIND_LOC_INVALID;
break;
}
ftdm_channel_add_var(ftdmchan, "isdn.prog_ind.loc", ftdm_sngisdn_progind_loc2str(val));
ftdm_call_add_var(&ftdmchan->caller_data, "isdn.prog_ind.loc", ftdm_sngisdn_progind_loc2str(val));
}
return FTDM_SUCCESS;
}
@@ -423,6 +461,89 @@ ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
return FTDM_SUCCESS;
}
ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
{
const char* string = NULL;
uint8_t len,val;
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.digits");
if ((string == NULL) || !(*string)) {
return FTDM_FAIL;
}
cgPtyNmb->eh.pres = PRSNT_NODEF;
len = strlen(string);
cgPtyNmb->nmbDigits.len = len;
cgPtyNmb->nmbDigits.pres = PRSNT_NODEF;
memcpy(cgPtyNmb->nmbDigits.val, string, len);
/* Screening Indicator */
cgPtyNmb->screenInd.pres = PRSNT_NODEF;
val = FTDM_SCREENING_INVALID;
string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.screening_ind");
if ((string != NULL) && (*string)) {
val = ftdm_str2ftdm_screening(string);
}
/* isdn.cg_pty2.screen_ind does not exist or we could not parse its value */
if (val == FTDM_SCREENING_INVALID) {
/* default to caller data screening ind */
cgPtyNmb->screenInd.val = caller_data->screen;
} else {
cgPtyNmb->screenInd.val = val;
}
/* Presentation Indicator */
cgPtyNmb->presInd0.pres = PRSNT_NODEF;
val = FTDM_PRES_INVALID;
string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.presentation_ind");
if ((string != NULL) && (*string)) {
val = ftdm_str2ftdm_presentation(string);
}
if (val == FTDM_PRES_INVALID) {
cgPtyNmb->presInd0.val = caller_data->pres;
} else {
cgPtyNmb->presInd0.val = val;
}
/* Numbering Plan Indicator */
cgPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
val = FTDM_NPI_INVALID;
string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.npi");
if ((string != NULL) && (*string)) {
val = ftdm_str2ftdm_npi(string);
}
if (val == FTDM_NPI_INVALID) {
cgPtyNmb->nmbPlanId.val = caller_data->cid_num.plan;
} else {
cgPtyNmb->nmbPlanId.val = val;
}
cgPtyNmb->typeNmb1.pres = PRSNT_NODEF;
/* Type of Number */
val = FTDM_TON_INVALID;
string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.ton");
if ((string != NULL) && (*string)) {
val = ftdm_str2ftdm_ton(string);
}
if (val == FTDM_TON_INVALID) {
cgPtyNmb->typeNmb1.val = caller_data->cid_num.type;
} else {
cgPtyNmb->typeNmb1.val = val;
}
return FTDM_SUCCESS;
}
ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
@@ -544,7 +665,7 @@ ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt)
ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
{
const char* clg_subaddr = NULL;
clg_subaddr = ftdm_channel_get_var(ftdmchan, "isdn.calling_subaddr");
clg_subaddr = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.calling_subaddr");
if ((clg_subaddr != NULL) && (*clg_subaddr)) {
unsigned len = strlen (clg_subaddr);
cgPtySad->eh.pres = PRSNT_NODEF;
@@ -561,11 +682,10 @@ ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
return FTDM_SUCCESS;
}
ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr)
{
ftdm_status_t status;
status = set_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, (ftdm_size_t*)&facilityStr->facilityStr.len);
status = set_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, (uint8_t*)&(facilityStr->facilityStr.len));
if (status == FTDM_SUCCESS) {
facilityStr->eh.pres = PRSNT_NODEF;
facilityStr->facilityStr.pres = PRSNT_NODEF;
@@ -573,13 +693,15 @@ ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr
return status;
}
ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t *data_len)
ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len)
{
int len;
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (caller_data->raw_data_len > 0 && caller_data->raw_data[0] == SNGISDN_Q931_FACILITY_IE_ID) {
*data_len = caller_data->raw_data[1];
memcpy(data, &caller_data->raw_data[2], *data_len);
len = caller_data->raw_data[1];
memcpy(data, &caller_data->raw_data[2], len);
*data_len = len;
return FTDM_SUCCESS;
}
return FTDM_FAIL;
@@ -591,7 +713,7 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s
int descr = prog_ind.descr;
int loc = prog_ind.loc;
str = ftdm_channel_get_var(ftdmchan, "isdn.prog_ind.descr");
str = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.prog_ind.descr");
if (str && *str) {
/* User wants to override progress indicator */
descr = ftdm_str2ftdm_sngisdn_progind_descr(str);
@@ -602,8 +724,8 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s
return FTDM_SUCCESS;
}
str = ftdm_channel_get_var(ftdmchan, "isdn.prog_ind.loc");
if (str && *str) {
str = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.prog_ind.loc");
if (str && *str) {
loc = ftdm_str2ftdm_sngisdn_progind_loc(str);
}
if (loc == SNGISDN_PROGIND_LOC_INVALID) {
@@ -672,6 +794,93 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s
return FTDM_SUCCESS;
}
ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId)
{
if (!ftdmchan) {
return FTDM_SUCCESS;
}
chanId->eh.pres = PRSNT_NODEF;
chanId->prefExc.pres = PRSNT_NODEF;
chanId->prefExc.val = IN_PE_EXCLSVE;
chanId->dChanInd.pres = PRSNT_NODEF;
chanId->dChanInd.val = IN_DSI_NOTDCHAN;
chanId->intIdentPres.pres = PRSNT_NODEF;
chanId->intIdentPres.val = IN_IIP_IMPLICIT;
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
/* BRI only params */
chanId->intType.pres = PRSNT_NODEF;
chanId->intType.val = IN_IT_BASIC;
chanId->infoChanSel.pres = PRSNT_NODEF;
chanId->infoChanSel.val = ftdmchan->physical_chan_id;
} else {
chanId->intType.pres = PRSNT_NODEF;
chanId->intType.val = IN_IT_OTHER;
chanId->infoChanSel.pres = PRSNT_NODEF;
chanId->infoChanSel.val = IN_ICS_B1CHAN;
chanId->chanMapType.pres = PRSNT_NODEF;
chanId->chanMapType.val = IN_CMT_BCHAN;
chanId->nmbMap.pres = PRSNT_NODEF;
chanId->nmbMap.val = IN_NM_CHNNMB;
chanId->codeStand1.pres = PRSNT_NODEF;
chanId->codeStand1.val = IN_CSTD_CCITT;
chanId->chanNmbSlotMap.pres = PRSNT_NODEF;
chanId->chanNmbSlotMap.len = 1;
chanId->chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
return FTDM_SUCCESS;
}
ftdm_status_t set_bear_cap_ie(ftdm_channel_t *ftdmchan, BearCap *bearCap)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
bearCap->eh.pres = PRSNT_NODEF;
bearCap->infoTranCap.pres = PRSNT_NODEF;
bearCap->infoTranCap.val = sngisdn_get_infoTranCap_from_user(ftdmchan->caller_data.bearer_capability);
bearCap->codeStand0.pres = PRSNT_NODEF;
bearCap->codeStand0.val = IN_CSTD_CCITT;
bearCap->infoTranRate0.pres = PRSNT_NODEF;
bearCap->infoTranRate0.val = IN_ITR_64KBIT;
bearCap->tranMode.pres = PRSNT_NODEF;
bearCap->tranMode.val = IN_TM_CIRCUIT;
if (!FTDM_SPAN_IS_BRI(ftdmchan->span)) {
/* Trillium stack rejests lyr1Ident on BRI, but Netbricks always sends it.
Check with Trillium if this ever causes calls to fail in the field */
/* PRI only params */
bearCap->usrInfoLyr1Prot.pres = PRSNT_NODEF;
bearCap->usrInfoLyr1Prot.val = sngisdn_get_usrInfoLyr1Prot_from_user(ftdmchan->caller_data.bearer_layer1);
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN &&
bearCap->usrInfoLyr1Prot.val == IN_UIL1_G711ULAW) {
/* We are bridging a call from T1 */
bearCap->usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
} else if (bearCap->usrInfoLyr1Prot.val == IN_UIL1_G711ALAW) {
/* We are bridging a call from E1 */
bearCap->usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
}
bearCap->lyr1Ident.pres = PRSNT_NODEF;
bearCap->lyr1Ident.val = IN_L1_IDENT;
}
return FTDM_SUCCESS;
}
ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd)
{
rstInd->eh.pres = PRSNT_NODEF;
rstInd->rstClass.pres = PRSNT_NODEF;
rstInd->rstClass.val = IN_CL_INDCHAN;
return FTDM_SUCCESS;
}
void sngisdn_t3_timeout(void* p_sngisdn_info)
{
@@ -36,14 +36,15 @@
#include "ftmod_sangoma_isdn_trace.h"
#define OCTET(x) (ieData[x-1] & 0xFF)
#define MAX_DECODE_STR_LEN 2000
void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end);
void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start);
uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi);
char* get_code_2_str(int code, struct code2str *pCodeTable);
void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len);
void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len);
char* get_code_2_str(int code, struct code2str *pCodeTable)
{
@@ -97,7 +98,43 @@ uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi)
return 0;
}
void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len)
void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
{
char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
sngisdn_decode_q921(data_str, data, data_len);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] s%d FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
ftdm_safe_free(data_str);
}
void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
{
uint8_t *raw_data;
ftdm_sigmsg_t sigev;
memset(&sigev, 0, sizeof(sigev));
sigev.span_id = signal_data->ftdm_span->span_id;
sigev.chan_id = signal_data->dchan->chan_id;
sigev.channel = signal_data->dchan;
sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
sigev.ev_data.logevent.dir = dir;
sigev.ev_data.logevent.level = 2;
/* TODO: Map trace to call ID here */
sigev.call_id = 0;
raw_data = ftdm_malloc(data_len);
ftdm_assert(raw_data, "Failed to malloc");
memcpy(raw_data, data, data_len);
sigev.raw.data = raw_data;
sigev.raw.len = data_len;
sigev.raw.autofree = 1;
ftdm_span_send_signal(signal_data->ftdm_span, &sigev);
}
void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len)
{
int str_len;
uint32_t i;
@@ -169,7 +206,43 @@ void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len)
return;
}
void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len)
void sngisdn_trace_interpreted_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
{
char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
sngisdn_decode_q931(data_str, data, data_len);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] %s FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
ftdm_safe_free(data_str);
}
void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
{
uint8_t *raw_data;
ftdm_sigmsg_t sigev;
memset(&sigev, 0, sizeof(sigev));
sigev.span_id = signal_data->ftdm_span->span_id;
sigev.chan_id = signal_data->dchan->chan_id;
sigev.channel = signal_data->dchan;
sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
sigev.ev_data.logevent.dir = dir;
sigev.ev_data.logevent.level = 3;
/* TODO: Map trace to call ID here */
raw_data = ftdm_malloc(data_len);
ftdm_assert(raw_data, "Failed to malloc");
memcpy(raw_data, data, data_len);
sigev.raw.data = raw_data;
sigev.raw.len = data_len;
sigev.raw.autofree = 1;
ftdm_span_send_signal(signal_data->ftdm_span, &sigev);
}
void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len)
{
uint32_t str_len;
uint8_t prot_disc, callRefFlag;
@@ -1589,7 +1589,7 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* if this is the first channel in the range */
@@ -1689,7 +1689,7 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* if this is the first channel in the range */
@@ -211,10 +211,10 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* add any special variables for the dialplan */
sprintf(nadi, "%d", siConEvnt->cgPtyNum.natAddrInd.val);
ftdm_channel_add_var(ftdmchan, "ss7_clg_nadi", nadi);
ftdm_call_add_var(&ftdmchan->caller_data, "ss7_clg_nadi", nadi);
sprintf(nadi, "%d", siConEvnt->cdPtyNum.natAddrInd.val);
ftdm_channel_add_var(ftdmchan, "ss7_cld_nadi", nadi);
ftdm_call_add_var(&ftdmchan->caller_data, "ss7_cld_nadi", nadi);
/* check if a COT test is requested */
@@ -2004,7 +2004,7 @@ ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* unlock the channel again before we exit */
@@ -2135,7 +2135,7 @@ ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* unlock the channel again before we exit */
@@ -502,6 +502,8 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/**************************************************************************/
case FTDM_CHANNEL_STATE_COLLECT: /* IAM received but wating on digits */
isup_intf = &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId];
if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
break;
@@ -521,8 +523,8 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/*now go to the RING state */
ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING);
} else if (i >= g_ftdm_sngss7_data.min_digits) {
SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, g_ftdm_sngss7_data.min_digits);
} else if (i >= isup_intf->min_digits) {
SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, isup_intf->min_digits);
/*now go to the RING state */
ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING);
@@ -532,7 +534,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
if (ftdmchan->last_state != FTDM_CHANNEL_STATE_IDLE) {
SS7_INFO_CHAN(ftdmchan,"Received %d out of %d so far: %s...starting T35\n",
i,
g_ftdm_sngss7_data.min_digits,
isup_intf->min_digits,
ftdmchan->caller_data.dnis.digits);
/* start ISUP t35 */
@@ -839,7 +841,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
SS7_DEBUG_CHAN(ftdmchan,"All reset flags cleared %s\n", "");
/* all flags are down so we can bring up the sig status */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal (ftdmchan->span, &sigev);
} /* if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) */
} /* if !blocked */
@@ -947,7 +949,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* if the sig_status is up...bring it down */
if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal (ftdmchan->span, &sigev);
}
@@ -1031,7 +1033,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status back up */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
}
@@ -1044,7 +1046,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* go back to the last state */
@@ -1056,7 +1058,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a BLA */
@@ -1074,7 +1076,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status up */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a uba */
@@ -1090,7 +1092,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a blo */
@@ -1108,7 +1110,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status up */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a ubl */
@@ -1147,7 +1149,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the channel signaling status to down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal (ftdmchan->span, &sigev);
/* remove any reset flags */
@@ -1520,9 +1522,6 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init)
/* initalize the global gen_config flag */
g_ftdm_sngss7_data.gen_config = 0;
/* min. number of digitis to wait for */
g_ftdm_sngss7_data.min_digits = 7;
/* function trace initizalation */
g_ftdm_sngss7_data.function_trace = 1;
g_ftdm_sngss7_data.function_trace_level = 7;
@@ -50,7 +50,7 @@
/******************************************************************************/
/* DEFINES ********************************************************************/
#define MAX_NAME_LEN 10
#define MAX_NAME_LEN 25
#define MAX_PATH 255
#define MAX_CIC_LENGTH 5
@@ -224,6 +224,7 @@ typedef struct sng_isup_intf {
uint32_t isap;
uint32_t clg_nadi;
uint32_t cld_nadi;
uint32_t min_digits;
uint16_t t4;
uint32_t t10;
uint32_t t11;
@@ -326,7 +327,6 @@ typedef struct sng_ss7_cfg {
typedef struct ftdm_sngss7_data {
sng_ss7_cfg_t cfg;
int gen_config;
int min_digits;
int function_trace;
int function_trace_level;
int message_trace;
@@ -187,7 +187,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
copy_cgPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cgPtyNum);
/* check if the user would like a custom NADI value for the calling Pty Num */
clg_nadi = ftdm_channel_get_var(ftdmchan, "ss7_clg_nadi");
clg_nadi = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_clg_nadi");
if ((clg_nadi != NULL) && (*clg_nadi)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling NADI value \"%s\"\n", clg_nadi);
iam.cgPtyNum.natAddrInd.val = atoi(clg_nadi);
@@ -196,7 +196,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
SS7_DEBUG_CHAN(ftdmchan,"No user supplied NADI value found for CLG, using \"%d\"\n", iam.cgPtyNum.natAddrInd.val);
}
cld_nadi = ftdm_channel_get_var(ftdmchan, "ss7_cld_nadi");
cld_nadi = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_cld_nadi");
if ((cld_nadi != NULL) && (*cld_nadi)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called NADI value \"%s\"\n", cld_nadi);
iam.cdPtyNum.natAddrInd.val = atoi(cld_nadi);
@@ -206,7 +206,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
}
/* check if the user would like us to send a clg_sub-address */
clg_subAddr = ftdm_channel_get_var(ftdmchan, "ss7_clg_subaddr");
clg_subAddr = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_clg_subaddr");
if ((clg_subAddr != NULL) && (*clg_subAddr)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling Sub-Address value \"%s\"\n", clg_subAddr);
@@ -245,7 +245,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
}
/* check if the user would like us to send a cld_sub-address */
cld_subAddr = ftdm_channel_get_var(ftdmchan, "ss7_cld_subaddr");
cld_subAddr = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_cld_subaddr");
if ((cld_subAddr != NULL) && (*cld_subAddr)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called Sub-Address value \"%s\"\n", cld_subAddr);
@@ -298,7 +298,8 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
iam.cgPtyNum.natAddrInd.val,
ftdmchan->caller_data.dnis.digits,
iam.cdPtyNum.natAddrInd.val);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -379,7 +380,7 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
ADDRCMPLT);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ACM\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -403,7 +404,7 @@ void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan)
5);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ANM\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -438,7 +439,7 @@ void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan)
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx REL cause=%d \n",
sngss7_info->circuit->cic,
ftdmchan->caller_data.hangup_cause );
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -461,7 +462,7 @@ void ft_to_sngss7_rlc (ftdm_channel_t * ftdmchan)
&rlc);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RLC\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -482,7 +483,7 @@ void ft_to_sngss7_rsc (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -503,7 +504,7 @@ void ft_to_sngss7_rsca (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC-RLC\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -524,7 +525,7 @@ void ft_to_sngss7_blo (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLO\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -545,7 +546,7 @@ void ft_to_sngss7_bla (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLA\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -567,7 +568,7 @@ ft_to_sngss7_ubl (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBL\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -588,7 +589,7 @@ void ft_to_sngss7_uba (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBA\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -609,7 +610,7 @@ void ft_to_sngss7_lpa (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx LPA\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -654,6 +655,7 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->rx_grs.range));
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -686,7 +688,8 @@ void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan)
sngss7_info->circuit->cic,
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->tx_grs.range));
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -735,7 +738,7 @@ void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan)
/* clean out the saved data */
memset(&sngss7_span->rx_cgb, 0x0, sizeof(sngss7_group_data_t));
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -785,6 +788,7 @@ void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan)
/* clean out the saved data */
memset(&sngss7_span->rx_cgu, 0x0, sizeof(sngss7_group_data_t));
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -835,6 +839,7 @@ void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan)
/* clean out the saved data */
memset(&sngss7_span->tx_cgb, 0x0, sizeof(sngss7_group_data_t));
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -885,6 +890,7 @@ void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan)
/* clean out the saved data */
memset(&sngss7_span->tx_cgu, 0x0, sizeof(sngss7_group_data_t));
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -142,7 +142,7 @@ int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *spa
if (!strcasecmp(var, "ch_map")) {
/**********************************************************************/
strcpy(isupCkt.ch_map, val);
strncpy(isupCkt.ch_map, val, MAX_CIC_MAP_LENGTH-1);
SS7_DEBUG("\tFound channel map \"%s\"\n", isupCkt.ch_map);
/**********************************************************************/
} else if (!strcasecmp(var, "typeCntrl")) {
@@ -393,7 +393,7 @@ static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset)
for (i = 0; i < num_parms; i++) {
/**********************************************************************/
if (!strcasecmp(parm->var, "name")) {
strcpy((char *)mtpLinkSet.name, parm->val);
strncpy((char *)mtpLinkSet.name, parm->val, MAX_NAME_LEN-1);
SS7_DEBUG("\tFound an \"mtp_linkset\" named = %s\n", mtpLinkSet.name);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "apc")) {
@@ -508,7 +508,7 @@ static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp_link_t *
/* try to match the parameter to what we expect */
/**********************************************************************/
if (!strcasecmp(parm->var, "name")) {
strcpy((char *)mtpLink->name, parm->val);
strncpy((char *)mtpLink->name, parm->val, MAX_NAME_LEN-1);
SS7_DEBUG("\tFound an \"mtp_link\" named = %s\n", mtpLink->name);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "span")) {
@@ -827,7 +827,7 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route)
/* try to match the parameter to what we expect */
/**********************************************************************/
if (!strcasecmp(parm->var, "name")) {
strcpy((char *)mtpRoute.name, parm->val);
strncpy((char *)mtpRoute.name, parm->val, MAX_NAME_LEN-1);
SS7_DEBUG("\tFound an \"mtp_route\" named = %s\n", mtpRoute.name);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "dpc")) {
@@ -999,7 +999,7 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
/* try to match the parameter to what we expect */
/**********************************************************************/
if (!strcasecmp(parm->var, "name")) {
strcpy((char *)sng_isup.name, parm->val);
strncpy((char *)sng_isup.name, parm->val, MAX_NAME_LEN-1);
SS7_DEBUG("\tFound an \"isup_interface\" named = %s\n", sng_isup.name);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "spc")) {
@@ -1047,6 +1047,11 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
SS7_DEBUG("\tFound MTP3 Route = %s\n", parm->val);
}
/**********************************************************************/
} else if (!strcasecmp(parm->var, "min_digits")) {
sng_isup.min_digits = atoi(parm->val);
SS7_DEBUG("\tFound min_digits = %d\n", sng_isup.min_digits);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "ssf")) {
if (!strcasecmp(parm->val, "nat")) {
sng_isup.ssf = SSF_NAT;
@@ -1067,8 +1072,8 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
/**********************************************************************/
} else if (!strcasecmp(parm->var, "license")) {
/**********************************************************************/
strcpy(g_ftdm_sngss7_data.cfg.license, parm->val);
strcpy(g_ftdm_sngss7_data.cfg.signature, parm->val);
strncpy(g_ftdm_sngss7_data.cfg.license, parm->val, MAX_PATH-1);
strncpy(g_ftdm_sngss7_data.cfg.signature, parm->val, MAX_PATH-1);
strcat(g_ftdm_sngss7_data.cfg.signature, ".sig");
SS7_DEBUG("\tFound license file = %s\n", g_ftdm_sngss7_data.cfg.license);
SS7_DEBUG("\tFound signature file = %s\n", g_ftdm_sngss7_data.cfg.signature);
@@ -1304,6 +1309,13 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
sng_isup.clg_nadi = 0x03;
}
/* check if the user requested min_digits value */
if (sng_isup.min_digits == 0) {
/* default to 7 */
sng_isup.min_digits = 7;
}
/* trickle down the SPC to all sub entities */
linkSetId = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].linkSetId;
@@ -1359,7 +1371,7 @@ static int ftmod_ss7_fill_in_mtpLink(sng_mtp_link_t *mtpLink)
}
/* fill in the information */
strcpy((char *)g_ftdm_sngss7_data.cfg.mtpLink[i].name, (char *)mtpLink->name);
strncpy((char *)g_ftdm_sngss7_data.cfg.mtpLink[i].name, (char *)mtpLink->name, MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.mtpLink[i].id = mtpLink->id;
@@ -1521,7 +1533,7 @@ static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet)
{
int i = mtpLinkSet->id;
strcpy((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (char *)mtpLinkSet->name);
strncpy((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (char *)mtpLinkSet->name, MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.mtpLinkSet[i].id = mtpLinkSet->id;
g_ftdm_sngss7_data.cfg.mtpLinkSet[i].apc = mtpLinkSet->apc;
@@ -1559,7 +1571,7 @@ static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route)
SS7_DEBUG("found existing mtp3_route, id is = %d\n", mtp3_route->id);
}
strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, (char *)mtp3_route->name);
strncpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, (char *)mtp3_route->name, MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.mtpRoute[i].id = mtp3_route->id;
g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc = mtp3_route->dpc;
@@ -1693,7 +1705,7 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
SS7_DEBUG("found existing isup interface, id is = %d\n", sng_isup->id);
}
strcpy((char *)g_ftdm_sngss7_data.cfg.isupIntf[i].name, (char *)sng_isup->name);
strncpy((char *)g_ftdm_sngss7_data.cfg.isupIntf[i].name, (char *)sng_isup->name, MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.isupIntf[i].id = sng_isup->id;
g_ftdm_sngss7_data.cfg.isupIntf[i].mtpRouteId = sng_isup->mtpRouteId;
@@ -1705,6 +1717,7 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
g_ftdm_sngss7_data.cfg.isupIntf[i].isap = sng_isup->isap;
g_ftdm_sngss7_data.cfg.isupIntf[i].cld_nadi = sng_isup->cld_nadi;
g_ftdm_sngss7_data.cfg.isupIntf[i].clg_nadi = sng_isup->clg_nadi;
g_ftdm_sngss7_data.cfg.isupIntf[i].min_digits = sng_isup->min_digits;
g_ftdm_sngss7_data.cfg.isupIntf[i].options = sng_isup->options;
if (sng_isup->t4 != 0) {
g_ftdm_sngss7_data.cfg.isupIntf[i].t4 = sng_isup->t4;
@@ -1976,7 +1989,7 @@ static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, i
return FTDM_FAIL;
}
strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[0].name, "self-route");
strncpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[0].name, "self-route", MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.mtpRoute[0].id = 0;
g_ftdm_sngss7_data.cfg.mtpRoute[0].dpc = spc;
@@ -2230,7 +2243,7 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot)
int lower;
int upper;
char tmp[5]; /*KONRAD FIX ME*/
char new_ch_map[MAX_CIC_LENGTH];
char new_ch_map[MAX_CIC_MAP_LENGTH];
memset(&tmp[0], '\0', sizeof(tmp));
memset(&new_ch_map[0], '\0', sizeof(new_ch_map));
@@ -2337,7 +2350,9 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot)
/* the the rest of ch_map to new_ch_map */
strncat(new_ch_map, &ch_map[x], strlen(&ch_map[x]));
/* set the new cic map to ch_map*/
memset(ch_map, '\0', sizeof(ch_map));
strcpy(ch_map, new_ch_map);
} else if (ch_map[x] == ',') {
@@ -2345,16 +2360,21 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot)
x++;
/* copy the rest of the list to new_ch_map */
memset(new_ch_map, '\0', sizeof(new_ch_map));
strcpy(new_ch_map, &ch_map[x]);
/* copy the new_ch_map over the old one */
memset(ch_map, '\0', sizeof(ch_map));
strcpy(ch_map, new_ch_map);
} else if (ch_map[x] == '\0') {
/* we're at the end of the string...copy the rest of the list to new_ch_map */
memset(new_ch_map, '\0', sizeof(new_ch_map));
strcpy(new_ch_map, &ch_map[x]);
/* set the new cic map to ch_map*/
memset(ch_map, '\0', sizeof(ch_map));
strcpy(ch_map, new_ch_map);
} else {
/* nothing to do */
@@ -811,13 +811,14 @@ static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *t
ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
}
if (ftdmchan->iostats.tx.idle_packets < tx_stats->wp_api_tx_hdr_number_of_frames_in_queue) {
ftdmchan->iostats.tx.idle_packets = tx_stats->wp_api_tx_hdr_tx_idle_packets;
if (ftdmchan->iostats.tx.idle_packets < tx_stats->wp_api_tx_hdr_tx_idle_packets) {
/* HDLC channels do not always transmit, so its ok for drivers to fill with idle
* also do not report idle warning when we just started transmitting */
if (ftdmchan->iostats.tx.packets && FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx idle: %d\n", ftdmchan->iostats.tx.idle_packets);
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx idle changed from %d to %d\n",
ftdmchan->iostats.tx.idle_packets, tx_stats->wp_api_tx_hdr_tx_idle_packets);
}
ftdmchan->iostats.tx.idle_packets = tx_stats->wp_api_tx_hdr_tx_idle_packets;
}
if (!ftdmchan->iostats.tx.packets) {
@@ -941,7 +942,6 @@ static FIO_WRITE_FUNCTION(wanpipe_write)
{
int bsent = 0;
int err = 0;
ftdm_time_t ms = 0;
wp_tdm_api_tx_hdr_t hdrframe;
/* Do we even need the headerframe here? on windows, we don't even pass it to the driver */
@@ -1051,16 +1051,34 @@ FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
for(i = 1; i <= span->chan_count; i++) {
ftdm_channel_t *ftdmchan = span->channels[i];
uint32_t chan_events = 0;
/* translate events from ftdm to libsnagoma. if the user don't specify which events to poll the
* channel for, we just use SANG_WAIT_OBJ_HAS_EVENTS */
if (poll_events) {
if (poll_events[j] & FTDM_READ) {
chan_events = SANG_WAIT_OBJ_HAS_INPUT;
}
if (poll_events[j] & FTDM_WRITE) {
chan_events |= SANG_WAIT_OBJ_HAS_OUTPUT;
}
if (poll_events[j] & FTDM_EVENTS) {
chan_events |= SANG_WAIT_OBJ_HAS_EVENTS;
}
} else {
chan_events = SANG_WAIT_OBJ_HAS_EVENTS;
}
#ifdef LIBSANGOMA_VERSION
if (!ftdmchan->io_data) {
continue; /* should never happen but happens when shutting down */
}
pfds[j] = ftdmchan->io_data;
inflags[j] = poll_events ? poll_events[j] : POLLPRI;
inflags[j] = chan_events;
#else
memset(&pfds[j], 0, sizeof(pfds[j]));
pfds[j].fd = span->channels[i]->sockfd;
pfds[j].events = poll_events ? poll_events[j] : POLLPRI;
pfds[j].events = chan_events;
#endif
/* The driver probably should be able to do this wink/flash/ringing by itself this is sort of a hack to make it work! */
+69 -39
View File
@@ -31,10 +31,14 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "private/ftdm_core.h"
#include "ftmod_zt.h"
/* used by dahdi to indicate there is no data available, but events to read */
#ifndef ELAST
#define ELAST 500
#endif
/**
* \brief Zaptel globals
*/
@@ -48,42 +52,48 @@ static struct {
float txgain;
} zt_globals;
#if defined(__FreeBSD__)
typedef unsigned long ioctlcmd;
#else
typedef int ioctlcmd;
#endif
/**
* \brief General IOCTL codes
*/
struct ioctl_codes {
int GET_BLOCKSIZE;
int SET_BLOCKSIZE;
int FLUSH;
int SYNC;
int GET_PARAMS;
int SET_PARAMS;
int HOOK;
int GETEVENT;
int IOMUX;
int SPANSTAT;
int MAINT;
int GETCONF;
int SETCONF;
int CONFLINK;
int CONFDIAG;
int GETGAINS;
int SETGAINS;
int SPANCONFIG;
int CHANCONFIG;
int SET_BUFINFO;
int GET_BUFINFO;
int AUDIOMODE;
int ECHOCANCEL;
int HDLCRAWMODE;
int HDLCFCSMODE;
int SPECIFY;
int SETLAW;
int SETLINEAR;
int GETCONFMUTE;
int ECHOTRAIN;
int SETTXBITS;
int GETRXBITS;
ioctlcmd GET_BLOCKSIZE;
ioctlcmd SET_BLOCKSIZE;
ioctlcmd FLUSH;
ioctlcmd SYNC;
ioctlcmd GET_PARAMS;
ioctlcmd SET_PARAMS;
ioctlcmd HOOK;
ioctlcmd GETEVENT;
ioctlcmd IOMUX;
ioctlcmd SPANSTAT;
ioctlcmd MAINT;
ioctlcmd GETCONF;
ioctlcmd SETCONF;
ioctlcmd CONFLINK;
ioctlcmd CONFDIAG;
ioctlcmd GETGAINS;
ioctlcmd SETGAINS;
ioctlcmd SPANCONFIG;
ioctlcmd CHANCONFIG;
ioctlcmd SET_BUFINFO;
ioctlcmd GET_BUFINFO;
ioctlcmd AUDIOMODE;
ioctlcmd ECHOCANCEL;
ioctlcmd HDLCRAWMODE;
ioctlcmd HDLCFCSMODE;
ioctlcmd SPECIFY;
ioctlcmd SETLAW;
ioctlcmd SETLINEAR;
ioctlcmd GETCONFMUTE;
ioctlcmd ECHOTRAIN;
ioctlcmd SETTXBITS;
ioctlcmd GETRXBITS;
};
/**
@@ -1183,7 +1193,6 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event)
}
return FTDM_FAIL;
}
/**
@@ -1202,12 +1211,19 @@ static FIO_READ_FUNCTION(zt_read)
if ((r = read(ftdmchan->sockfd, data, *datalen)) > 0) {
break;
}
ftdm_sleep(10);
if (r == 0) {
errs--;
else if (r == 0) {
ftdm_sleep(10);
if (errs) errs--;
}
else {
if (errno == EAGAIN || errno == EINTR)
continue;
if (errno == ELAST)
break;
ftdm_log(FTDM_LOG_ERROR, "read failed: %s\n", strerror(errno));
}
}
if (r > 0) {
*datalen = r;
if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) {
@@ -1215,7 +1231,9 @@ static FIO_READ_FUNCTION(zt_read)
}
return FTDM_SUCCESS;
}
else if (errno == ELAST) {
return FTDM_SUCCESS;
}
return r == 0 ? FTDM_TIMEOUT : FTDM_FAIL;
}
@@ -1236,6 +1254,7 @@ static FIO_WRITE_FUNCTION(zt_write)
bytes += 2;
}
tryagain:
w = write(ftdmchan->sockfd, data, bytes);
if (w >= 0) {
@@ -1243,6 +1262,17 @@ static FIO_WRITE_FUNCTION(zt_write)
return FTDM_SUCCESS;
}
if (errno == ELAST) {
zt_event_t zt_event_id = 0;
if (ioctl(ftdmchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed retrieving event after ELAST on write: %s\n", strerror(errno));
return FTDM_FAIL;
}
/* we should enqueue this event somewhere so it can be retrieved by the user, for now, dropping it to see what it is! */
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dropping event %d to be able to write data\n", zt_event_id);
goto tryagain;
}
return FTDM_FAIL;
}