Merge remote branch 'fsorig/master' into nfas

Conflicts:
	libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c
	libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
This commit is contained in:
David Yat Sin committed 2012-09-03 22:34:13 -04:00
commit 3a57b0bed6
1605 files changed
+170690 -121271

No files matched your search

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -473,7 +473,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
sig.span_id = ftdmchan->span_id;
sig.channel = ftdmchan;
ftdm_assert(interval != 0, NULL);
ftdm_assert(interval != 0, "Invalid interval");
if (!dial_timeout) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Not waiting for dial tone to dial number %s\n", ftdmchan->caller_data.dnis.digits);
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Anthony Minessale II
* Copyright (c) 2008-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Anthony Minessale II
* Copyright (c) 2008-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
File diff suppressed because it is too large. Load diff
+168 -128
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -469,10 +469,15 @@ static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request)
}
if (new_chan && new_chan->state == FTDM_CHANNEL_STATE_DOWN) {
isdn_data->channels_local_crv[gen->CRV] = new_chan;
struct Q931_Call *call = NULL;
memset(&new_chan->caller_data, 0, sizeof(new_chan->caller_data));
ftdm_set_flag(new_chan, FTDM_CHANNEL_OUTBOUND);
ftdm_set_state_locked(new_chan, FTDM_CHANNEL_STATE_DIALING);
call = Q931GetCallByCRV(&isdn_data->q931, gen->CRV);
Q931CallSetPrivate(call, new_chan);
switch(gen->MesType) {
case Q931mes_ALERTING:
new_chan->init_state = FTDM_CHANNEL_STATE_PROGRESS_MEDIA;
@@ -539,21 +544,17 @@ static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent *
{
Q931_TrunkInfo_t *trunk = NULL;
ftdm_isdn_data_t *isdn_data = NULL;
ftdm_span_t *zspan = NULL;
ftdm_span_t *span = priv;
assert(span);
assert(call);
assert(event);
trunk = Q931CallGetTrunk(call);
assert(trunk);
zspan = Q931CallGetPrivate(call);
if (!zspan) {
zspan = priv;
Q931CallSetPrivate(call, zspan);
}
assert(zspan);
isdn_data = zspan->signal_data;
isdn_data = span->signal_data;
assert(isdn_data);
if (Q931CallIsGlobal(call)) {
/*
@@ -575,7 +576,7 @@ static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent *
* Try to get associated zap channel
* and init sigmsg struct if there is one
*/
ftdmchan = Q931CallIsOutgoing(call) ? isdn_data->channels_local_crv[call_crv] : isdn_data->channels_remote_crv[call_crv];
ftdmchan = Q931CallGetPrivate(call);
if (ftdmchan) {
memset(&sig, 0, sizeof(ftdm_sigmsg_t));
sig.chan_id = ftdmchan->chan_id;
@@ -598,7 +599,9 @@ static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent *
return;
}
if (ftdm_channel_get_state(ftdmchan) != FTDM_CHANNEL_STATE_DOWN) {
if (ftdm_channel_get_state(ftdmchan) != FTDM_CHANNEL_STATE_DOWN &&
ftdm_channel_get_state(ftdmchan) != FTDM_CHANNEL_STATE_HANGUP_COMPLETE)
{
ftdm_log(FTDM_LOG_DEBUG, "Channel %d:%d not in DOWN state, cleaning up\n",
ftdm_channel_get_span_id(ftdmchan),
ftdm_channel_get_id(ftdmchan));
@@ -763,29 +766,23 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
assert(span != NULL);
assert(isdn_data != NULL);
/*
* Support code for the new event handling system
* Remove this as soon as we have the new api to set up calls
*/
#ifdef __OLD__
if (gen->CRV) {
struct Q931_Call *call;
call = Q931GetCallByCRV(&isdn_data->q931, gen->CRV);
if (call && !Q931CallGetPrivate(call)) {
ftdm_log(FTDM_LOG_DEBUG, "Storing reference to current span in call %d [0x%x]\n", gen->CRV, gen->CRV);
Q931CallSetPrivate(call, span);
/* ftdm channel is stored in call private */
if (call) {
ftdmchan = Q931CallGetPrivate(call);
if (!ftdmchan) {
ftdm_log(FTDM_LOG_DEBUG, "[s%d] No channel associated to call [%#x] private\n",
ftdm_span_get_id(span), Q931CallGetCRV(call));
}
}
#else
if (call && !Q931CallGetPrivate(call)) {
ftdm_log(FTDM_LOG_DEBUG, "Storing reference to current span in call %d [0x%x]\n", gen->CRV, gen->CRV);
Q931CallSetPrivate(call, span);
}
#endif
ftdm_log(FTDM_LOG_DEBUG, "Yay I got an event! Type:[%02x] Size:[%d] CRV: %d (%#hx, CTX: %s)\n", gen->MesType, gen->Size, gen->CRV, gen->CRV, gen->CRVFlag ? "Terminator" : "Originator");
#ifdef __TODO_OR_REMOVE__
ftdm_log(FTDM_LOG_DEBUG, "Yay I got an event! Type:[%02x] Size:[%d] CRV: %d (%#hx, CTX: %s)\n",
gen->MesType, gen->Size, gen->CRV, gen->CRV, gen->CRVFlag ? "Terminator" : "Originator");
#ifdef __TODO__
/*
* This code block is needed for isdn_channel_request()
* isdn_data->outbound_crv has been removed so another way to pass data around is required
*/
if (gen->CRVFlag && (caller_data = isdn_data->outbound_crv[gen->CRV])) {
if (chan_id) {
caller_data->chan_id = chan_id;
@@ -808,18 +805,10 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
return 0;
}
#endif
if (gen->CRVFlag) {
ftdmchan = isdn_data->channels_local_crv[gen->CRV];
} else {
ftdmchan = isdn_data->channels_remote_crv[gen->CRV];
}
ftdm_log(FTDM_LOG_DEBUG, "ftdmchan %x (%d:%d) source isdn_data->channels_%s_crv[%#hx]\n",
ftdm_log(FTDM_LOG_DEBUG, "ftdmchan %p (%d:%d) via CRV[%#hx]\n",
ftdmchan,
((ftdmchan) ? ftdm_channel_get_span_id(ftdmchan) : -1),
((ftdmchan) ? ftdm_channel_get_id(ftdmchan) : -1),
((gen->CRVFlag) ? "local" : "remote"),
gen->CRV);
if (gen->ProtDisc == 3) {
@@ -874,12 +863,14 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
uint32_t i;
for (i = 1; i < ftdm_span_get_chan_count(span); i++) {
ftdmchan = ftdm_span_get_channel(span, chan_id);
/* Skip channels that are down and D-Channels (#OpenZAP-39) */
if (ftdm_channel_get_state(span->channels[i]) == FTDM_CHANNEL_STATE_DOWN ||
ftdm_channel_get_type(span->channels[i]) == FTDM_CHAN_TYPE_DQ921)
if (ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DOWN ||
ftdm_channel_get_type(ftdmchan) == FTDM_CHAN_TYPE_DQ921)
continue;
ftdm_set_state_locked(span->channels[i], FTDM_CHANNEL_STATE_RESTART);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
}
}
}
@@ -898,6 +889,10 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
}
}
else if (gen->MesType == Q931mes_RELEASE_COMPLETE && ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DIALTONE) {
/* Go DOWN */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
}
else if ((gen->MesType == Q931mes_RELEASE && ftdm_channel_get_state(ftdmchan) <= FTDM_CHANNEL_STATE_UP) ||
(gen->MesType == Q931mes_RELEASE_COMPLETE && ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DIALING)) {
@@ -906,7 +901,6 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
*/
Q931ie_Cause *cause = Q931GetIEPtr(gen->Cause, gen->buf);
ftdm_sigmsg_t sig;
ftdm_status_t status;
memset(&sig, 0, sizeof(sig));
sig.span_id = ftdm_channel_get_span_id(ftdmchan);
@@ -915,14 +909,15 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
sig.channel->caller_data.hangup_cause = (cause) ? cause->Value : FTDM_CAUSE_NORMAL_UNSPECIFIED;
sig.event_id = FTDM_SIGEVENT_STOP;
status = ftdm_span_send_signal(span, &sig);
ftdm_span_send_signal(span, &sig);
ftdm_log(FTDM_LOG_DEBUG, "Received %s in state %s, requested hangup for channel %d:%d\n", what,
ftdm_channel_get_state_str(ftdmchan),
ftdm_channel_get_span_id(ftdmchan),
ftdm_channel_get_id(ftdmchan));
} else {
ftdm_log(FTDM_LOG_DEBUG, "Ignoring %s on channel %d\n", what, ftdm_channel_get_id(ftdmchan));
ftdm_log(FTDM_LOG_DEBUG, "Ignoring %s on channel %d in state %s\n", what,
ftdm_channel_get_id(ftdmchan), ftdm_channel_get_state_str(ftdmchan));
}
} else {
ftdm_log(FTDM_LOG_CRIT, "Received %s with no matching channel %d\n", what, chan_id);
@@ -983,7 +978,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
int fail_cause = 0;
int fail = 1;
if (ftdmchan && ftdmchan == isdn_data->channels_remote_crv[gen->CRV]) {
if (ftdmchan && ftdmchan == Q931CallGetPrivate(call)) {
ftdm_log(FTDM_LOG_INFO, "Duplicate SETUP message(?) for Channel %d:%d ~ %d:%d in state %s [ignoring]\n",
ftdm_channel_get_span_id(ftdmchan),
ftdm_channel_get_id(ftdmchan),
@@ -1039,7 +1034,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
}
}
if (!callednum || !strlen((char *)callednum->Digit)) {
if (!callednum || ftdm_strlen_zero((char *)callednum->Digit)) {
if (FTDM_SPAN_IS_NT(span)) {
ftdm_log(FTDM_LOG_NOTICE, "No destination number found, assuming overlap dial\n");
overlap_dial++;
@@ -1080,7 +1075,6 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
if (ftdmchan && ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DOWN) {
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(ftdmchan);
isdn_data->channels_remote_crv[gen->CRV] = ftdmchan;
memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data));
if (ftdmchan->call_data) {
@@ -1095,19 +1089,12 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
if (!overlap_dial) {
isdn_get_number(callednum, caller_data->dnis.digits);
}
#ifdef __TODO_OR_REMOVE__
ftdmchan->caller_data.CRV = gen->CRV;
#endif
#if 0 /* FIXME */
if (cplen > sizeof(caller_data->raw_data)) {
cplen = sizeof(caller_data->raw_data);
}
#endif
ftdmchan->caller_data.call_reference = gen->CRV;
Q931CallSetPrivate(call, ftdmchan);
gen->CRVFlag = !(gen->CRVFlag);
#if 0 /* FIXME */
memcpy(caller_data->raw_data, msg, cplen);
caller_data->raw_data_len = cplen;
#endif
fail = 0;
}
}
@@ -1134,7 +1121,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
}
if (ftdmchan) {
ftdm_log(FTDM_LOG_CRIT, "Channel is busy\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Channel is busy\n");
} else {
ftdm_log(FTDM_LOG_CRIT, "Failed to open channel for new setup message\n");
}
@@ -1191,7 +1178,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
case Q931mes_CALL_PROCEEDING:
{
if (ftdmchan) {
ftdm_log(FTDM_LOG_CRIT, "Received CALL PROCEEDING message for channel %d\n", ftdm_channel_get_id(ftdmchan));
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Received CALL PROCEEDING message for channel\n");
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
} else {
ftdm_log(FTDM_LOG_CRIT, "Received CALL PROCEEDING with no matching channel %d\n", chan_id);
@@ -1201,7 +1188,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
case Q931mes_CONNECT_ACKNOWLEDGE:
{
if (ftdmchan) {
ftdm_log(FTDM_LOG_DEBUG, "Received CONNECT_ACK message for channel %d\n", ftdm_channel_get_id(ftdmchan));
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Received CONNECT_ACK message for channel\n");
} else {
ftdm_log(FTDM_LOG_DEBUG, "Received CONNECT_ACK with no matching channel %d\n", chan_id);
}
@@ -1211,7 +1198,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
case Q931mes_INFORMATION:
{
if (ftdmchan) {
ftdm_log(FTDM_LOG_CRIT, "Received INFORMATION message for channel %d\n", ftdm_channel_get_id(ftdmchan));
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Received INFORMATION message for channel\n");
if (ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DIALTONE) {
char digit = '\0';
@@ -1305,19 +1292,25 @@ static int ftdm_isdn_921_21(void *pvt, L2UCHAR *msg, L2INT mlen)
static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
{
ftdm_isdn_data_t *isdn_data = ftdmchan->span->signal_data;
ftdm_span_t *span = ftdm_channel_get_span(ftdmchan);
ftdm_isdn_data_t *isdn_data = NULL;
ftdm_sigmsg_t sig;
ftdm_status_t status;
#if 1 /* FIXME caller_data.raw_data does not exist anymore, see docs/variables.txt for more info */
Q931mes_Generic empty_gen;
Q931mes_Generic *gen = &empty_gen;
memset(&empty_gen, 0, sizeof(empty_gen)) ;
#else
Q931mes_Generic *gen = (Q931mes_Generic *) ftdmchan->caller_data.raw_data;
#endif
struct Q931_Call *call = NULL;
Q931InitMesGeneric(gen);
isdn_data = span->signal_data;
assert(isdn_data);
call = Q931GetCallByCRV(&isdn_data->q931, ftdmchan->caller_data.call_reference);
if (call) {
gen->CRV = Q931CallGetCRV(call);
gen->CRVFlag = Q931CallGetDirection(call) == Q931_DIRECTION_INBOUND ? 1 : 0;
}
ftdm_log(FTDM_LOG_DEBUG, "%d:%d STATE [%s]\n",
ftdm_channel_get_span_id(ftdmchan),
@@ -1329,17 +1322,17 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
sig.chan_id = ftdm_channel_get_id(ftdmchan);
sig.channel = ftdmchan;
/* Acknowledge channel state change */
ftdm_channel_complete_state(ftdmchan);
switch (ftdm_channel_get_state(ftdmchan)) {
case FTDM_CHANNEL_STATE_DOWN:
{
if (gen->CRV) {
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
isdn_data->channels_local_crv[gen->CRV] = NULL;
} else {
isdn_data->channels_remote_crv[gen->CRV] = NULL;
}
Q931CallSetPrivate(call, NULL);
Q931ReleaseCRV(&isdn_data->q931, gen->CRV);
}
ftdmchan->caller_data.call_reference = 0;
ftdm_channel_close(&ftdmchan);
}
break;
@@ -1348,15 +1341,10 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_PROGRESS;
if ((status = ftdm_span_send_signal(ftdm_channel_get_span(ftdmchan), &sig) != FTDM_SUCCESS)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
}
} else {
int crv = gen->CRV;
Q931InitMesGeneric(gen);
gen->MesType = Q931mes_CALL_PROCEEDING;
gen->CRV = crv;
gen->CRVFlag = 1; /* inbound */
if (FTDM_SPAN_IS_NT(ftdm_channel_get_span(ftdmchan))) {
Q931ie_ChanID ChanID;
@@ -1396,7 +1384,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_START;
if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
}
}
}
@@ -1406,7 +1394,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_UNSPECIFIED;
sig.event_id = FTDM_SIGEVENT_RESTART;
status = ftdm_span_send_signal(span, &sig);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
@@ -1414,17 +1402,16 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
}
} else {
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
return;
}
}
gen->MesType = Q931mes_ALERTING;
gen->CRVFlag = 1; /* inbound call */
Q931Rx43(&isdn_data->q931, gen, gen->Size);
}
}
@@ -1434,21 +1421,19 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_UP;
if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
}
} else {
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
return;
}
}
gen->MesType = Q931mes_CONNECT;
gen->BearerCap = 0;
gen->CRVFlag = 1; /* inbound call */
#if 0 /* FIXME */
Q931Rx43(&isdn_data->q931, gen, ftdmchan->caller_data.raw_data_len);
#endif
Q931Rx43(&isdn_data->q931, gen, gen->Size);
}
}
break;
@@ -1560,19 +1545,18 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
gen->HLComp = Q931AppendIE(gen, (L3UCHAR *) &HLComp);
Q931Rx43(&isdn_data->q931, gen, gen->Size);
isdn_data->channels_local_crv[gen->CRV] = ftdmchan;
/*
* Support code for the new event handling system
* Remove this as soon as we have the new api to set up calls
*/
if (gen->CRV) {
struct Q931_Call *call;
call = Q931GetCallByCRV(&isdn_data->q931, gen->CRV);
if (call) {
ftdm_log(FTDM_LOG_DEBUG, "Storing reference to current span in call %d [0x%x]\n", gen->CRV, gen->CRV);
Q931CallSetPrivate(call, ftdm_channel_get_span(ftdmchan));
Q931CallSetPrivate(call, ftdmchan);
ftdmchan->caller_data.call_reference = gen->CRV;
}
}
}
@@ -1585,7 +1569,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
Q931Rx43(&isdn_data->q931, gen, gen->Size);
}
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
}
break;
case FTDM_CHANNEL_STATE_HANGUP:
@@ -1593,9 +1577,8 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(ftdmchan);
Q931ie_Cause cause;
ftdm_log(FTDM_LOG_DEBUG, "Hangup: Direction %s\n", ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? "Outbound" : "Inbound");
gen->CRVFlag = ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? 0 : 1;
ftdm_log(FTDM_LOG_DEBUG, "Hangup: Call direction %s\n",
ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? "Outbound" : "Inbound");
cause.IEId = Q931ie_CAUSE;
cause.Size = sizeof(Q931ie_Cause);
@@ -1612,7 +1595,13 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
* inbound call [was: number unknown (= not found in routing state)]
* (in Q.931 spec terms: Reject request)
*/
gen->MesType = Q931mes_RELEASE_COMPLETE;
if (!FTDM_SPAN_IS_NT(span)) {
gen->MesType = Q931mes_RELEASE_COMPLETE; /* TE mode: Reject call */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
} else {
gen->MesType = Q931mes_DISCONNECT; /* NT mode: Disconnect and wait */
//ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
}
//cause.Value = (unsigned char) FTDM_CAUSE_UNALLOCATED;
cause.Value = (unsigned char) caller_data->hangup_cause;
@@ -1621,8 +1610,8 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
Q931Rx43(&isdn_data->q931, gen, gen->Size);
/* we're done, release channel */
//ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
////ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
//ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
}
else if (ftdm_channel_get_last_state(ftdmchan) <= FTDM_CHANNEL_STATE_PROGRESS) {
/*
@@ -1636,7 +1625,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
Q931Rx43(&isdn_data->q931, gen, gen->Size);
/* this will be triggered by the RELEASE_COMPLETE reply */
/* ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); */
/* ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); */
}
else {
/*
@@ -1653,13 +1642,13 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
break;
case FTDM_CHANNEL_STATE_TERMINATING:
{
ftdm_log(FTDM_LOG_DEBUG, "Terminating: Direction %s\n", ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? "Outbound" : "Inbound");
ftdm_log(FTDM_LOG_DEBUG, "Terminating: Call direction %s\n",
ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? "Outbound" : "Inbound");
sig.event_id = FTDM_SIGEVENT_STOP;
status = ftdm_span_send_signal(span, &sig);
gen->MesType = Q931mes_RELEASE;
gen->CRVFlag = ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? 0 : 1;
Q931Rx43(&isdn_data->q931, gen, gen->Size);
}
default:
@@ -1679,11 +1668,8 @@ static __inline__ void check_state(ftdm_span_t *span)
if (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) {
ftdm_channel_lock(chan);
ftdm_clear_flag(chan, FTDM_CHANNEL_STATE_CHANGE);
state_advance(chan);
ftdm_channel_complete_state(chan);
ftdm_channel_unlock(chan);
}
}
@@ -1820,7 +1806,6 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
teletone_generation_session_t ts = {{{{0}}}};;
unsigned char frame[1024];
int x, interval;
int offset = 0;
ftdm_log(FTDM_LOG_DEBUG, "ISDN tones thread starting.\n");
ftdm_set_flag(isdn_data, FTDM_ISDN_TONES_RUNNING);
@@ -1865,6 +1850,7 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
for (x = 1; x <= ftdm_span_get_chan_count(span); x++) {
ftdm_channel_t *chan = ftdm_span_get_channel(span, x);
ftdm_size_t len = sizeof(frame), rlen;
ftdm_isdn_bchan_data_t *data = chan->call_data;
if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_DQ921) {
continue;
@@ -1878,7 +1864,6 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
switch (ftdm_channel_get_state(chan)) {
case FTDM_CHANNEL_STATE_DIALTONE:
{
ftdm_isdn_bchan_data_t *data = (ftdm_isdn_bchan_data_t *)chan->call_data;
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
/* check overlap dial timeout first before generating tone */
@@ -1951,13 +1936,24 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
continue;
}
/*
* Teletone operates on SLIN data (2 bytes per sample).
* Convert the length of non-SLIN codecs, so we read
* the right amount of samples from the buffer.
*/
if (chan->effective_codec != FTDM_CODEC_SLIN) {
len *= 2;
}
/* seek to current offset */
ftdm_buffer_seek(dt_buffer, offset);
ftdm_buffer_seek(dt_buffer, data->offset);
/*
* ftdm_channel_read() can read up to sizeof(frame) bytes
* (in certain situations). Avoid overflowing the stack (and smashing dt_buffer)
* if the codec is not slin and we had to double the length.
*/
len = ftdm_min(len, sizeof(frame));
rlen = ftdm_buffer_read_loop(dt_buffer, frame, len);
if (chan->effective_codec != FTDM_CODEC_SLIN) {
@@ -1969,6 +1965,12 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
codec_func = fio_slin2alaw;
}
/*
* Convert SLIN to native format (a-law/u-law),
* input size is 2 bytes per sample, output size
* (after conversion) is one byte per sample
* (= max. half the input size).
*/
if (codec_func) {
status = codec_func(frame, sizeof(frame), &rlen);
} else {
@@ -1976,7 +1978,21 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
goto done;
}
}
ftdm_channel_write(chan, frame, sizeof(frame), &rlen);
if (ftdm_channel_write(chan, frame, sizeof(frame), &rlen) == FTDM_SUCCESS) {
/*
* Advance offset in teletone buffer by amount
* of data actually written to channel.
*/
if (chan->effective_codec != FTDM_CODEC_SLIN) {
data->offset += rlen << 1; /* Teletone buffer is in SLIN (= rlen * 2) */
} else {
data->offset += rlen;
}
/* Limit offset to [0..Rate(Samples/s)-1] in SLIN (2 bytes per sample) units. */
data->offset %= (ts.rate << 1);
}
}
/*
@@ -1985,11 +2001,6 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
if (!gated) {
ftdm_sleep(interval);
}
offset += (ts.rate / (1000 / interval)) << 1;
if (offset >= ts.rate) {
offset = 0;
}
}
done:
@@ -2055,10 +2066,13 @@ static void *ftdm_isdn_run(ftdm_thread_t *me, void *obj)
break;
default:
{
errs = 0;
if (flags & FTDM_READ) {
len = sizeof(frame);
if (ftdm_channel_read(isdn_data->dchan, frame, &len) == FTDM_SUCCESS) {
if (ftdm_channel_read(isdn_data->dchan, frame, &len) != FTDM_SUCCESS) {
ftdm_log_chan_msg(isdn_data->dchan, FTDM_LOG_ERROR, "Failed to read from D-Channel\n");
continue;
}
if (len > 0) {
#ifdef HAVE_PCAP
if (isdn_pcap_capture_both(isdn_data)) {
isdn_pcap_write(isdn_data, frame, len, ISDN_PCAP_INCOMING);
@@ -2066,6 +2080,9 @@ static void *ftdm_isdn_run(ftdm_thread_t *me, void *obj)
#endif
Q921QueueHDLCFrame(&isdn_data->q921, frame, (int)len);
Q921Rx12(&isdn_data->q921);
/* Successful read, reset error counter */
errs = 0;
}
} else {
ftdm_log(FTDM_LOG_DEBUG, "No Read FLAG!\n");
@@ -2209,7 +2226,7 @@ static ftdm_state_map_t isdn_state_map = {
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_DIALTONE, FTDM_END},
{FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
{FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_DOWN, FTDM_END}
},
{
ZSD_INBOUND,
@@ -2676,11 +2693,24 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(isdn_configure_span)
isdn_data = malloc(sizeof(*isdn_data));
assert(isdn_data != NULL);
memset(isdn_data, 0, sizeof(*isdn_data));
isdn_data->mode = Q931_TE;
memset(isdn_data, 0, sizeof(*isdn_data));
dialect = Q931_Dialect_Q931;
/* Use trunk_mode span parameter to set default */
switch (ftdm_span_get_trunk_mode(span)) {
case FTDM_TRUNK_MODE_NET:
ftdm_log(FTDM_LOG_INFO, "Span '%s' [s%d] defaulting to NET mode\n",
ftdm_span_get_name(span), ftdm_span_get_id(span));
isdn_data->mode = Q931_NT;
break;
default:
ftdm_log(FTDM_LOG_INFO, "Span '%s' [s%d] defaulting to USER mode\n",
ftdm_span_get_name(span), ftdm_span_get_id(span));
isdn_data->mode = Q931_TE;
break;
}
for (i = 0; ftdm_parameters[i].var; i++) {
const char *var = ftdm_parameters[i].var;
const char *val = ftdm_parameters[i].val;
@@ -2744,6 +2774,16 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(isdn_configure_span)
digit_timeout = DEFAULT_DIGIT_TIMEOUT;
}
/* Check if modes match and log a message if they do not. Just to be on the safe side. */
if (isdn_data->mode == Q931_TE && ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_NET) {
ftdm_log(FTDM_LOG_WARNING, "Span '%s' signalling set up for TE/CPE/USER mode, while port is running in NT/NET mode. You may want to check your 'trunk_mode' settings.\n",
ftdm_span_get_name(span));
}
else if (isdn_data->mode == Q931_NT && ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_CPE) {
ftdm_log(FTDM_LOG_WARNING, "Span '%s' signalling set up for NT/NET mode, while port is running in TE/CPE/USER mode. You may want to check your 'trunk_mode' settings.\n",
ftdm_span_get_name(span));
}
/* allocate per b-chan data */
if (isdn_data->mode == Q931_NT) {
ftdm_isdn_bchan_data_t *data;
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -67,9 +67,6 @@ struct ftdm_isdn_data {
int32_t mode;
int32_t digit_timeout;
ftdm_isdn_opts_t opts;
ftdm_caller_data_t *outbound_crv[32768];
ftdm_channel_t *channels_local_crv[32768];
ftdm_channel_t *channels_remote_crv[32768];
#ifdef HAVE_PCAP
struct pcap_context *pcap;
#endif
@@ -81,7 +78,8 @@ typedef struct ftdm_isdn_data ftdm_isdn_data_t;
/* b-channel private data */
struct ftdm_isdn_bchan_data
{
int32_t digit_timeout;
ftdm_time_t digit_timeout;
int offset; /* offset in teletone buffer */
};
typedef struct ftdm_isdn_bchan_data ftdm_isdn_bchan_data_t;
File diff suppressed because it is too large. Load diff
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, Anthony Minessale II
* Copyright (c) 2009-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,18 +30,21 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
typedef enum {
SERVICE_CHANGE_STATUS_INSERVICE = 0,
SERVICE_CHANGE_STATUS_MAINTENANCE = 1,
SERVICE_CHANGE_STATUS_OUTOFSERVICE = 2
} service_change_status_t;
#ifndef FTMOD_LIBPRI_H
#define FTMOD_LIBPRI_H
#include "freetdm.h"
#include "lpwrap_pri.h"
#define OVERLAP_TIMEOUT_MS_DEFAULT 5000 /* 5 sec */
#define OVERLAP_TIMEOUT_MS_MIN 3000 /* 3 sec */
#define OVERLAP_TIMEOUT_MS_MAX 30000 /* 30 sec */
typedef enum {
SERVICE_CHANGE_STATUS_INSERVICE = 0,
SERVICE_CHANGE_STATUS_MAINTENANCE,
SERVICE_CHANGE_STATUS_OUTOFSERVICE
} service_change_status_t;
typedef enum {
FTMOD_LIBPRI_OPT_NONE = 0,
FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL = (1 << 0),
@@ -72,15 +75,41 @@ struct ftdm_libpri_data {
int mode;
int dialect;
int overlap; /*!< Overlap dial flags */
int overlap_timeout_ms; /*!< Overlap dial timeout */
unsigned int layer1;
unsigned int ton;
unsigned int service_message_support;
lpwrap_pri_t spri;
/* MSN filter */
ftdm_hash_t *msn_hash;
ftdm_mutex_t *msn_mutex;
};
typedef struct ftdm_libpri_data ftdm_libpri_data_t;
/*
* b-channel flags
*/
enum {
FTDM_LIBPRI_B_NONE = 0,
FTDM_LIBPRI_B_REMOTE_RESTART = (1 << 0), /*!< Remote triggered channel restart */
};
/**
* Per-b-channel private data
*/
struct ftdm_libpri_b_chan {
struct lpwrap_timer t302; /*!< T302 overlap receive timer */
ftdm_channel_t *channel; /*!< back-pointer to b-channel */
q931_call *call; /*!< libpri opaque call handle */
uint32_t flags; /*!< channel flags */
};
typedef struct ftdm_libpri_b_chan ftdm_libpri_b_chan_t;
#endif
/* For Emacs:
+246 -129
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, Anthony Minessale II
* Copyright (c) 2009-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,51 +36,7 @@
#include "private/ftdm_core.h"
#include "lpwrap_pri.h"
#ifndef HAVE_GETTIMEOFDAY
#ifdef WIN32
#include <mmsystem.h>
static __inline int gettimeofday(struct timeval *tp, void *nothing)
{
#ifdef WITHOUT_MM_LIB
SYSTEMTIME st;
time_t tt;
struct tm tmtm;
/* mktime converts local to UTC */
GetLocalTime (&st);
tmtm.tm_sec = st.wSecond;
tmtm.tm_min = st.wMinute;
tmtm.tm_hour = st.wHour;
tmtm.tm_mday = st.wDay;
tmtm.tm_mon = st.wMonth - 1;
tmtm.tm_year = st.wYear - 1900; tmtm.tm_isdst = -1;
tt = mktime (&tmtm);
tp->tv_sec = tt;
tp->tv_usec = st.wMilliseconds * 1000;
#else
/**
** The earlier time calculations using GetLocalTime
** had a time resolution of 10ms.The timeGetTime, part
** of multimedia apis offer a better time resolution
** of 1ms.Need to link against winmm.lib for this
**/
unsigned long Ticks = 0;
unsigned long Sec =0;
unsigned long Usec = 0;
Ticks = timeGetTime();
Sec = Ticks/1000;
Usec = (Ticks - (Sec*1000))*1000;
tp->tv_sec = Sec;
tp->tv_usec = Usec;
#endif /* WITHOUT_MM_LIB */
(void)nothing;
return 0;
}
#endif /* WIN32 */
#endif /* HAVE_GETTIMEOFDAY */
static struct lpwrap_pri_event_list LPWRAP_PRI_EVENT_LIST[] = {
static struct lpwrap_pri_event_list LPWRAP_PRI_EVENT_LIST[LPWRAP_PRI_EVENT_MAX] = {
{0, LPWRAP_PRI_EVENT_ANY, "ANY"},
{1, LPWRAP_PRI_EVENT_DCHAN_UP, "DCHAN_UP"},
{2, LPWRAP_PRI_EVENT_DCHAN_DOWN, "DCHAN_DOWN"},
@@ -103,8 +59,6 @@ static struct lpwrap_pri_event_list LPWRAP_PRI_EVENT_LIST[] = {
{19, LPWRAP_PRI_EVENT_IO_FAIL, "IO_FAIL"},
};
#define LINE "--------------------------------------------------------------------------------"
const char *lpwrap_pri_event_str(lpwrap_pri_event_t event_id)
{
if (event_id < 0 || event_id >= LPWRAP_PRI_EVENT_MAX)
@@ -170,6 +124,10 @@ static int __pri_lpwrap_write(struct pri *pri, void *buf, int buflen)
return (int)buflen;
}
/*
* Unified init function for BRI + PRI libpri spans
*/
int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int debug)
{
int ret = -1;
@@ -179,115 +137,255 @@ int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *
spri->span = span;
if (!spri->dchan) {
ftdm_log(FTDM_LOG_ERROR, "No D-Channel available, unable to create PRI\n");
ftdm_log(FTDM_LOG_ERROR, "No D-Channel available, unable to create BRI/PRI\n");
return ret;
}
if ((spri->pri = pri_new_cb(spri->dchan->sockfd, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri))) {
unsigned char buf[4] = { 0 };
size_t buflen = sizeof(buf), len = 0;
pri_set_debug(spri->pri, debug);
#ifdef HAVE_LIBPRI_AOC
pri_aoc_events_enable(spri->pri, 1);
#endif
ftdm_channel_write(spri->dchan, buf, buflen, &len);
ret = 0;
} else {
ftdm_log(FTDM_LOG_ERROR, "Unable to create PRI\n");
if (ftdm_mutex_create(&spri->timer_mutex) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Failed to create timer list mutex\n");
return ret;
}
return ret;
}
int lpwrap_init_bri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int ptp, int debug)
{
int ret = -1;
switch (ftdm_span_get_trunk_type(span)) {
case FTDM_TRUNK_E1:
case FTDM_TRUNK_J1:
case FTDM_TRUNK_T1:
spri->pri = pri_new_cb(spri->dchan->sockfd, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri);
break;
#ifdef HAVE_LIBPRI_BRI
memset(spri, 0, sizeof(struct lpwrap_pri));
spri->dchan = dchan;
spri->span = span;
if (!spri->dchan) {
ftdm_log(FTDM_LOG_ERROR, "No D-Channel available, unable to create BRI\n");
case FTDM_TRUNK_BRI:
spri->pri = pri_new_bri_cb(spri->dchan->sockfd, 1, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri);
break;
case FTDM_TRUNK_BRI_PTMP:
spri->pri = pri_new_bri_cb(spri->dchan->sockfd, 0, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri);
break;
#endif
default:
ftdm_log(FTDM_LOG_CRIT, "Invalid/unsupported trunk type '%s'\n",
ftdm_span_get_trunk_type_str(span));
ftdm_mutex_destroy(&spri->timer_mutex);
return ret;
}
if ((spri->pri = pri_new_bri_cb(spri->dchan->sockfd, ptp, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri))) {
unsigned char buf[4] = { 0 };
size_t buflen = sizeof(buf), len = 0;
if (spri->pri) {
pri_set_debug(spri->pri, debug);
#ifdef HAVE_LIBPRI_AOC
pri_aoc_events_enable(spri->pri, 1);
#endif
ftdm_channel_write(spri->dchan, buf, buflen, &len);
ret = 0;
} else {
ftdm_log(FTDM_LOG_ERROR, "Unable to create BRI\n");
ftdm_log(FTDM_LOG_CRIT, "Unable to create BRI/PRI\n");
ftdm_mutex_destroy(&spri->timer_mutex);
}
#else
ftdm_log(FTDM_LOG_ERROR, "Installed libpri version (%s) has no BRI support\n",
pri_get_version());
#endif
return ret;
}
int lpwrap_one_loop(struct lpwrap_pri *spri)
#define timeval_to_ms(x) \
(((ftdm_time_t)(x)->tv_sec * 1000) + (ftdm_time_t)((x)->tv_usec / 1000))
int lpwrap_start_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer, const uint32_t timeout_ms, timeout_handler callback)
{
fd_set rfds, efds;
struct timeval now = {0,0}, *next = NULL;
struct lpwrap_timer **prev, *cur;
if (!spri || !timer || timer->timeout)
return -1;
ftdm_log_chan(spri->dchan, FTDM_LOG_DEBUG, "-- Starting timer %p with timeout %u ms\n",
timer, timeout_ms);
timer->timeout = ftdm_current_time_in_ms() + timeout_ms;
timer->callback = callback;
timer->next = NULL;
ftdm_mutex_lock(spri->timer_mutex);
for (prev = &spri->timer_list, cur = spri->timer_list; cur; prev = &(*prev)->next, cur = cur->next) {
if (cur->timeout < timer->timeout) {
*prev = timer;
timer->next = cur;
break;
}
}
if (!cur) {
*prev = timer;
}
ftdm_mutex_unlock(spri->timer_mutex);
return 0;
}
int lpwrap_stop_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer)
{
struct lpwrap_timer **prev, *cur;
if (!spri || !timer)
return -1;
if (!timer->timeout)
return 0;
ftdm_log_chan(spri->dchan, FTDM_LOG_DEBUG, "-- Stopping timer %p\n", timer);
ftdm_mutex_lock(spri->timer_mutex);
for (prev = &spri->timer_list, cur = spri->timer_list; cur; prev = &(*prev)->next, cur = cur->next) {
if (cur == timer) {
*prev = cur->next;
break;
}
}
ftdm_mutex_unlock(spri->timer_mutex);
timer->next = NULL;
timer->timeout = 0;
timer->callback = NULL;
return 0;
}
static struct lpwrap_timer *lpwrap_timer_next(struct lpwrap_pri *spri)
{
return spri ? spri->timer_list : NULL;
}
static int lpwrap_run_expired(struct lpwrap_pri *spri, ftdm_time_t now_ms)
{
struct lpwrap_timer *expired_list = NULL;
struct lpwrap_timer **prev, *cur;
if (!spri || !spri->timer_list)
return 0;
ftdm_mutex_lock(spri->timer_mutex);
/* Move all timers to expired list */
expired_list = spri->timer_list;
for (prev = &expired_list, cur = expired_list; cur; prev = &(*prev)->next, cur = cur->next) {
if (cur->timeout > now_ms) {
*prev = NULL;
break;
}
}
/* Move non-expired timer to front of timer_list (or clear list if there are none) */
spri->timer_list = cur;
ftdm_mutex_unlock(spri->timer_mutex);
/* fire callbacks */
while ((cur = expired_list)) {
expired_list = cur->next;
if (cur->callback)
cur->callback(spri, cur);
/* stop timer */
cur->next = NULL;
cur->timeout = 0;
cur->callback = NULL;
}
return 0;
}
#define LPWRAP_MAX_TIMEOUT_MS 100
#define LPWRAP_MAX_ERRORS 2
int lpwrap_run_pri_once(struct lpwrap_pri *spri)
{
struct timeval *next = NULL;
struct lpwrap_timer *timer = NULL;
pri_event *event = NULL;
event_handler handler;
int sel;
ftdm_wait_flag_t flags;
ftdm_time_t now_ms, next_ms, timeout_ms, tmp_ms;
int ret;
if (spri->on_loop) {
if ((sel = spri->on_loop(spri)) < 0) {
return sel;
if ((ret = spri->on_loop(spri)) < 0)
return FTDM_FAIL;
}
/* Default timeout when no scheduled events are pending */
timeout_ms = LPWRAP_MAX_TIMEOUT_MS;
next_ms = 0;
now_ms = ftdm_current_time_in_ms();
/*
* Get the next scheduled timer from libpri to set the maximum timeout,
* but limit it to MAX_TIMEOUT_MS (100ms).
*/
if ((next = pri_schedule_next(spri->pri))) {
next_ms = timeval_to_ms(next);
if (now_ms >= next_ms) {
/* Already late, handle timeout */
timeout_ms = 0;
} else {
/* Calculate new timeout and limit it to MAX_TIMEOUT_MS miliseconds */
tmp_ms = ftdm_min(next_ms - now_ms, LPWRAP_MAX_TIMEOUT_MS);
timeout_ms = ftdm_min(timeout_ms, tmp_ms);
}
}
if (spri->errs >= 2) {
spri->errs = 0;
return -1;
/*
* Next lpwrap_timer timeout
*/
if ((timer = lpwrap_timer_next(spri))) {
if (now_ms >= timer->timeout) {
/* Already late, handle timeout */
timeout_ms = 0;
} else {
/* Calculate new timeout and limit it to MAX_TIMEOUT_MS miliseconds */
tmp_ms = ftdm_min(timer->timeout - now_ms, LPWRAP_MAX_TIMEOUT_MS);
timeout_ms = ftdm_min(timeout_ms, tmp_ms);
}
}
FD_ZERO(&rfds);
FD_ZERO(&efds);
/* */
if (timeout_ms > 0) {
flags = FTDM_READ | FTDM_EVENTS;
ret = ftdm_channel_wait(spri->dchan, &flags, timeout_ms);
#ifdef _MSC_VER
//Windows macro for FD_SET includes a warning C4127: conditional expression is constant
#pragma warning(push)
#pragma warning(disable:4127)
#endif
if (spri->flags & LPWRAP_PRI_ABORT)
return FTDM_SUCCESS;
FD_SET(pri_fd(spri->pri), &rfds);
FD_SET(pri_fd(spri->pri), &efds);
if (ret == FTDM_TIMEOUT) {
now_ms = ftdm_current_time_in_ms();
#ifdef _MSC_VER
#pragma warning(pop)
#endif
now.tv_sec = 0;
now.tv_usec = 100000;
sel = select(pri_fd(spri->pri) + 1, &rfds, NULL, &efds, &now);
if (!sel) {
if ((next = pri_schedule_next(spri->pri))) {
gettimeofday(&now, NULL);
if (now.tv_sec >= next->tv_sec && (now.tv_usec >= next->tv_usec || next->tv_usec <= 100000)) {
//ftdm_log(FTDM_LOG_DEBUG, "Check event\n");
if (next) {
if (next_ms < now_ms) {
ftdm_log_chan(spri->dchan, FTDM_LOG_DEBUG, "pri timer %d ms late\n",
(int)(now_ms - next_ms));
}
event = pri_schedule_run(spri->pri);
}
if (timer) {
if (timer->timeout < now_ms) {
ftdm_log_chan(spri->dchan, FTDM_LOG_DEBUG, "lpwrap timer %d ms late\n",
(int)(now_ms - timer->timeout));
}
lpwrap_run_expired(spri, now_ms);
}
} else if (flags & (FTDM_READ | FTDM_EVENTS)) {
event = pri_check_event(spri->pri);
}
} else {
/*
* Scheduled event has already expired, handle it immediately
*/
if (next) {
event = pri_schedule_run(spri->pri);
}
if (timer) {
lpwrap_run_expired(spri, now_ms);
}
} else if (sel > 0) {
event = pri_check_event(spri->pri);
}
if (spri->flags & LPWRAP_PRI_ABORT)
return FTDM_SUCCESS;
if (event) {
event_handler handler;
/* 0 is catchall event handler */
if (event->e < 0 || event->e >= LPWRAP_PRI_EVENT_MAX) {
handler = spri->eventmap[0];
@@ -303,28 +401,47 @@ int lpwrap_one_loop(struct lpwrap_pri *spri)
ftdm_log(FTDM_LOG_CRIT, "No event handler found for event %d.\n", event->e);
}
}
return sel;
return FTDM_SUCCESS;
}
int lpwrap_run_pri(struct lpwrap_pri *spri)
{
int ret = 0;
for (;;) {
if ((ret = lpwrap_one_loop(spri)) < 0) {
#ifndef WIN32 //This needs to be adressed fror WIN32 still
if (errno == EINTR){
/* Igonore an interrupted system call */
continue;
}
#endif
ftdm_log(FTDM_LOG_CRIT, "Error = %i [%s]\n", ret, strerror(errno));
while (!(spri->flags & LPWRAP_PRI_ABORT)) {
ret = lpwrap_run_pri_once(spri);
if (ret) {
ftdm_log(FTDM_LOG_ERROR, "Error = %d, [%s]\n",
ret, strerror(errno));
spri->errs++;
} else {
spri->errs = 0;
}
if (!ftdm_running())
break;
if (spri->errs >= LPWRAP_MAX_ERRORS) {
ftdm_log(FTDM_LOG_CRIT, "Too many errors on span, restarting\n");
spri->errs = 0;
break;
}
}
return ret;
}
int lpwrap_stop_pri(struct lpwrap_pri *spri)
{
spri->flags |= LPWRAP_PRI_ABORT;
return FTDM_SUCCESS;
}
int lpwrap_destroy_pri(struct lpwrap_pri *spri)
{
if (spri->timer_mutex)
ftdm_mutex_destroy(&spri->timer_mutex);
return FTDM_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, Anthony Minessale II
* Copyright (c) 2009-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -92,10 +92,14 @@ typedef enum {
} lpwrap_pri_switch_t;
typedef enum {
LPWRAP_PRI_READY = (1 << 0)
LPWRAP_PRI_READY = (1 << 0),
LPWRAP_PRI_ABORT = (1 << 1)
} lpwrap_pri_flag_t;
struct lpwrap_pri;
struct lpwrap_timer;
typedef int (*timeout_handler)(struct lpwrap_pri *, struct lpwrap_timer *);
typedef int (*event_handler)(struct lpwrap_pri *, lpwrap_pri_event_t, pri_event *);
typedef int (*loop_handler)(struct lpwrap_pri *);
@@ -108,6 +112,8 @@ struct lpwrap_pri {
event_handler eventmap[LPWRAP_PRI_EVENT_MAX];
loop_handler on_loop;
int errs;
struct lpwrap_timer *timer_list;
ftdm_mutex_t *timer_mutex;
};
typedef struct lpwrap_pri lpwrap_pri_t;
@@ -118,15 +124,21 @@ struct lpwrap_pri_event_list {
const char *name;
};
struct lpwrap_timer {
struct lpwrap_timer *next;
ftdm_time_t timeout;
timeout_handler callback;
};
int lpwrap_start_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer, const uint32_t timeout_ms, timeout_handler callback);
int lpwrap_stop_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer);
#define LPWRAP_MAP_PRI_EVENT(spri, event, func) spri.eventmap[event] = func;
const char *lpwrap_pri_event_str(lpwrap_pri_event_t event_id);
int lpwrap_one_loop(struct lpwrap_pri *spri);
int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int debug);
int lpwrap_init_bri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int ptp, int debug);
int lpwrap_run_pri(struct lpwrap_pri *spri);
#define lpwrap_run_bri(x) lpwrap_run_pri(x)
int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int debug);
int lpwrap_destroy_pri(struct lpwrap_pri *spri);
int lpwrap_run_pri_once(struct lpwrap_pri *spri);
int lpwrap_run_pri(struct lpwrap_pri *spri);
int lpwrap_stop_pri(struct lpwrap_pri *spri);
#endif
File diff suppressed because it is too large. Load diff
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -782,7 +782,7 @@ static ftdm_status_t ftdm_pritap_sig_read(ftdm_channel_t *ftdmchan, void *data,
return FTDM_FAIL;
}
if (sizeread != size) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "read from peer channel only %d bytes!\n", sizeread);
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "read from peer channel only %"FTDM_SIZE_FMT" bytes!\n", sizeread);
return FTDM_FAIL;
}
@@ -854,7 +854,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_pritap_configure_span)
}
if (!dchan) {
ftdm_log(FTDM_LOG_ERROR, "No d-channel specified in freetdm.conf!\n", ftdm_trunk_type2str(span->trunk_type));
ftdm_log(FTDM_LOG_ERROR, "No d-channel specified in freetdm.conf!\n");
return FTDM_FAIL;
}
+3 -3
View File
@@ -1557,10 +1557,10 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
intval = atoi(val);
if (intval < 0) {
r2conf.mf_dump_size = FTDM_IO_DUMP_DEFAULT_BUFF_SIZE;
ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with default mf_dump_size = %d bytes\n", span->name, r2conf.mf_dump_size);
ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with default mf_dump_size = %"FTDM_SIZE_FMT" bytes\n", span->name, r2conf.mf_dump_size);
} else {
r2conf.mf_dump_size = intval;
ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with mf_dump_size = %d bytes\n", span->name, r2conf.mf_dump_size);
ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with mf_dump_size = %"FTDM_SIZE_FMT" bytes\n", span->name, r2conf.mf_dump_size);
}
} else if (!strcasecmp(var, "allow_collect_calls")) {
r2conf.allow_collect_calls = ftdm_true(val);
@@ -1970,7 +1970,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
r2data->monitor_thread_id = syscall(SYS_gettid);
#endif
ftdm_log(FTDM_LOG_DEBUG, "OpenR2 monitor thread %lu started.\n", r2data->monitor_thread_id);
ftdm_log(FTDM_LOG_DEBUG, "OpenR2 monitor thread %u started.\n", r2data->monitor_thread_id);
r2chan = NULL;
chaniter = ftdm_span_get_chan_iterator(span, NULL);
if (!chaniter) {
@@ -451,17 +451,17 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
/* get an interrupt queue for this span */
if (ftdm_queue_get_interrupt(span->pendingchans, &ftdm_sangoma_isdn_int[0]) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a ftdm_interrupt for span = %s!\n", span->name);
ftdm_log(FTDM_LOG_CRIT, "Failed to get a ftdm_interrupt for span = %s!\n", span->name);
goto ftdm_sangoma_isdn_run_exit;
}
if (ftdm_queue_get_interrupt(span->pendingsignals, &ftdm_sangoma_isdn_int[1]) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a signal interrupt for span = %s!\n", span->name);
ftdm_log(FTDM_LOG_CRIT, "Failed to get a signal interrupt for span = %s!\n", span->name);
goto ftdm_sangoma_isdn_run_exit;
}
if (ftdm_queue_get_interrupt(signal_data->event_queue, &ftdm_sangoma_isdn_int[2]) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a event interrupt for span = %s!\n", span->name);
ftdm_log(FTDM_LOG_CRIT, "Failed to get a event interrupt for span = %s!\n", span->name);
goto ftdm_sangoma_isdn_run_exit;
}
@@ -528,6 +528,7 @@ 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_called_subaddr(ftdm_channel_t *ftdmchan, CdPtySad *cdPtySad);
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_network_specific_fac(ftdm_channel_t *ftdmchan, NetFac *netFac);
@@ -131,7 +131,7 @@ static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span
/* can be > 1 for some BRI variants */
break;
default:
ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type));
ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported trunktype:%s\n", span->name, ftdm_trunk_type2str(span->trunk_type));
return FTDM_FAIL;
}
@@ -523,7 +523,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
parse_yesno(var, val, &signal_data->restart_opt);
} else if (!strcasecmp(var, "channel-restart-timeout")) {
signal_data->restart_timeout = atoi(val);
} else if (!strcasecmp(var, "local-number")) {
} else if (!strcasecmp(var, "local-number")) {
if (add_local_number(val, span) != FTDM_SUCCESS) {
return FTDM_FAIL;
}
@@ -719,7 +719,11 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.clrGlr = FALSE; /* in case of glare, do not clear local call */
cfg.t.cfg.s.inDLSAP.statEnqOpt = TRUE;
cfg.t.cfg.s.inDLSAP.rstOpt = TRUE;
if (signal_data->ftdm_span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
cfg.t.cfg.s.inDLSAP.rstOpt = FALSE;
} else {
cfg.t.cfg.s.inDLSAP.rstOpt = TRUE;
}
} else {
cfg.t.cfg.s.inDLSAP.ackOpt = FALSE;
cfg.t.cfg.s.inDLSAP.intType = USER;
@@ -841,19 +845,17 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.tmr.t308.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t308.val = 4;
cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t310.val = 120;
if (signal_data->timer_t308 > 0) {
cfg.t.cfg.s.inDLSAP.tmr.t308.val = signal_data->timer_t308;
}
if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t310.val = 10;
cfg.t.cfg.s.inDLSAP.tmr.t312.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t312.val = cfg.t.cfg.s.inDLSAP.tmr.t303.val+2;
} else {
cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t310.val = 120;
cfg.t.cfg.s.inDLSAP.tmr.t312.enb = FALSE;
}
@@ -967,7 +969,7 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.dChannelNum = 0; /* Unused for BRI */
cfg.t.cfg.s.inDLSAP.nmbBearChan = NUM_BRI_CHANNELS_PER_SPAN;
cfg.t.cfg.s.inDLSAP.firstBChanNum = 1;
cfg.t.cfg.s.inDLSAP.callRefLen = 1;
cfg.t.cfg.s.inDLSAP.callRefLen = 1;
cfg.t.cfg.s.inDLSAP.teiAlloc = IN_STATIC;
cfg.t.cfg.s.inDLSAP.intCfg = IN_INTCFG_PTPT;
break;
@@ -1023,7 +1025,13 @@ ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span)
cfg.t.cfg.s.inLCe.sapId = signal_data->link_id;
cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE;
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
/* Stack will send Restart CFM's each time link is established (TEI negotiated),
and we do not want thi s event */
cfg.t.cfg.s.inLCe.lnkUpDwnInd = FALSE;
} else {
cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE;
}
if (FTDM_SPAN_IS_BRI(span)) {
/* tCon Timer causes unwanted hangup on BRI links
@@ -1225,7 +1233,7 @@ uint8_t sng_isdn_stack_switchtype(sngisdn_switchtype_t switchtype)
case SNGISDN_SWITCH_INSNET:
return SW_INSNET;
case SNGISDN_SWITCH_INVALID:
ftdm_log(FTDM_LOG_ERROR, "%s:Invalid switchtype:%d\n", switchtype);
ftdm_log(FTDM_LOG_ERROR, "Invalid switchtype: %d\n", switchtype);
break;
}
return 0;
@@ -493,7 +493,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
if (cnStEvnt->sndCmplt.eh.pres || num_digits >= min_digits) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
} else {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "received %d of %d digits\n", num_digits, min_digits);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "received %"FTDM_SIZE_FMT" of %"FTDM_SIZE_FMT" digits\n", num_digits, min_digits);
}
}
break;
@@ -509,7 +509,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
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);
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unhandled INFO (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
break;
}
}
@@ -966,6 +966,12 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
break;
case 2: /* overlap sending */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_COLLECT:
/* T302 Timeout reached */
/* Send the call to user, and see if they accept it */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T302 Timer expired, proceeding with call\n");
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
break;
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_RINGING:
@@ -1196,7 +1202,16 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
return;
}
if (rstEvnt->rstInd.eh.pres == PRSNT_NODEF && rstEvnt->rstInd.rstClass.pres == PRSNT_NODEF) {
ftdm_log(FTDM_LOG_DEBUG, "%s: Processing RESTART CFM (suId:%u dChan:%d ces:%d %s(%d))\n",
signal_data->ftdm_span->name,
suId, dChan, ces,
(evntType == IN_LNK_DWN)?"LNK_DOWN":
(evntType == IN_LNK_UP)?"LNK_UP":
(evntType == IN_INDCHAN)?"b-channel":
(evntType == IN_LNK_DWN_DM_RLS)?"NFAS service procedures":
(evntType == IN_SWCHD_BU_DCHAN)?"NFAS switchover to backup":"Unknown", evntType);
if (rstEvnt->rstInd.eh.pres == PRSNT_NODEF && rstEvnt->rstInd.rstClass.pres == PRSNT_NODEF) {
switch(rstEvnt->rstInd.rstClass.val) {
case IN_CL_INDCHAN: /* Indicated b-channel */
if (rstEvnt->chanId.eh.pres) {
@@ -1342,28 +1357,29 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
}
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 IND on invalid channel:%d\n", chan_no);
} else {
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)) {
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
if (ftdmchan->physical_chan_id == chan_no) {
sngisdn_bring_down(ftdmchan);
}
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)) {
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
if (sngisdn_info->ces == ces && ftdmchan->physical_chan_id == chan_no) {
sngisdn_bring_down(ftdmchan);
}
ftdm_iterator_free(chaniter);
}
ftdm_iterator_free(chaniter);
} 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_bring_down((ftdm_channel_t*)ftdm_iterator_current(curr));
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
if (sngisdn_info->ces == ces) {
sngisdn_bring_down(ftdmchan);
}
}
ftdm_iterator_free(chaniter);
}
@@ -67,6 +67,7 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
set_calling_num(ftdmchan, &conEvnt.cgPtyNmb);
set_calling_num2(ftdmchan, &conEvnt.cgPtyNmb2);
set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad);
set_called_subaddr(ftdmchan, &conEvnt.cdPtySad);
set_redir_num(ftdmchan, &conEvnt.redirNmb);
set_calling_name(ftdmchan, &conEvnt);
set_network_specific_fac(ftdmchan, &conEvnt.netFac[0]);
@@ -1084,7 +1084,7 @@ void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...)
switch (level) {
case SNG_LOGLEVEL_DEBUG:
ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s\n", data);
break;
case SNG_LOGLEVEL_WARN:
if ( strncmp(data, "Invalid Q.921/Q.931 frame", 25) ) {
@@ -1092,21 +1092,21 @@ void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...)
}
break;
case SNG_LOGLEVEL_INFO:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data);
break;
case SNG_LOGLEVEL_STATS:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data);
break;
case SNG_LOGLEVEL_ERROR:
ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s\n", data);
/*ftdm_assert(0, "Got an error from stack");*/
break;
case SNG_LOGLEVEL_CRIT:
ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s\n", data);
/* ftdm_assert(0, "Got an error from stack"); */
break;
default:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data);
break;
}
ftdm_safe_free(data);
@@ -453,7 +453,7 @@ ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
}
memset(subaddress, 0, sizeof(subaddress));
if(cgPtySad->sadInfo.len >= sizeof(subaddress)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Calling Party Subaddress exceeds local size limit (len:%d max:%d)\n", cgPtySad->sadInfo.len, sizeof(subaddress));
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Calling Party Subaddress exceeds local size limit (len:%d max:%"FTDM_SIZE_FMT")\n", cgPtySad->sadInfo.len, sizeof(subaddress));
cgPtySad->sadInfo.len = sizeof(subaddress)-1;
}
@@ -847,6 +847,26 @@ ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
return FTDM_SUCCESS;
}
ftdm_status_t set_called_subaddr(ftdm_channel_t *ftdmchan, CdPtySad *cdPtySad)
{
const char* cld_subaddr = NULL;
cld_subaddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.called_subaddr");
if (!ftdm_strlen_zero(cld_subaddr)) {
unsigned len = strlen (cld_subaddr);
cdPtySad->eh.pres = PRSNT_NODEF;
cdPtySad->typeSad.pres = 1;
cdPtySad->typeSad.val = 0; /* NSAP */
cdPtySad->oddEvenInd.pres = 1;
cdPtySad->oddEvenInd.val = 0;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Called Party Subaddress:%s\n", cld_subaddr);
cdPtySad->sadInfo.pres = 1;
cdPtySad->sadInfo.len = len;
memcpy(cdPtySad->sadInfo.val, cld_subaddr, len);
}
return FTDM_SUCCESS;
}
ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr)
{
ftdm_status_t status;
@@ -1198,7 +1218,7 @@ void sngisdn_restart_timeout(void *p_signal_data)
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
ftdm_log(FTDM_LOG_DEBUG, "s%d:Did not receive a RESTART from remote switch in %d ms - restarting\n", span->name, signal_data->restart_timeout);
ftdm_log(FTDM_LOG_DEBUG, "s%s:Did not receive a RESTART from remote switch in %d ms - restarting\n", span->name, signal_data->restart_timeout);
chaniter = ftdm_span_get_chan_iterator(span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
@@ -152,7 +152,7 @@ static ftdm_status_t att_courtesy_vru(ftdm_channel_t *ftdmchan, sngisdn_transfer
goto done;
}
if (strlen(val) > COURTESY_TRANSFER_MAX_DATA_SIZE) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Data exceeds max size (len:%d max:%d), cannot perform transfer\n", strlen(val), COURTESY_TRANSFER_MAX_DATA_SIZE);
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Data exceeds max size (len:%"FTDM_SIZE_FMT" max:%d), cannot perform transfer\n", strlen(val), COURTESY_TRANSFER_MAX_DATA_SIZE);
goto done;
}
memcpy(sngisdn_info->transfer_data.tdata.att_courtesy_vru.data, val, strlen(val));
@@ -99,17 +99,18 @@ int ft_to_sngss7_cfg_all(void)
return 1;
} else {
SS7_INFO("Started Stack Manager!\n");
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM_STARTED);
}
/* check if the configuration had a Relay Channel */
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY_PRESENT)) {
/* start up the relay task */
if (sng_isup_init_relay()) {
SS7_CRITICAL("Failed to start Relay\n");
return 1;
} else {
SS7_INFO("Started Relay!\n");
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY_STARTED);
}
/* run general configuration on the relay task */
@@ -122,12 +123,13 @@ int ft_to_sngss7_cfg_all(void)
} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY)) */
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_PRESENT)) {
if (sng_isup_init_cc()) {
SS7_CRITICAL("Failed to start Call-Control\n");
return 1;
} else {
SS7_INFO("Started Call-Control!\n");
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_STARTED);
}
if (ftmod_ss7_cc_gen_config()) {
SS7_CRITICAL("CC General configuration FAILED!\n");
@@ -143,12 +145,13 @@ int ft_to_sngss7_cfg_all(void)
}
} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC)) */
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_PRESENT)) {
if (sng_isup_init_isup()) {
SS7_CRITICAL("Failed to start ISUP\n");
return 1;
} else {
SS7_INFO("Started ISUP!\n");
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_STARTED);
}
if (ftmod_ss7_isup_gen_config()) {
SS7_CRITICAL("ISUP General configuration FAILED!\n");
@@ -158,12 +161,13 @@ int ft_to_sngss7_cfg_all(void)
}
} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) */
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3_PRESENT)) {
if (sng_isup_init_mtp3()) {
SS7_CRITICAL("Failed to start MTP3\n");
return 1;
} else {
SS7_INFO("Started MTP3!\n");
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3_STARTED);
}
if (ftmod_ss7_mtp3_gen_config()) {
@@ -174,18 +178,20 @@ int ft_to_sngss7_cfg_all(void)
}
} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3)) */
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_PRESENT)) {
if (sng_isup_init_mtp2()) {
SS7_CRITICAL("Failed to start MTP2\n");
return 1;
} else {
SS7_INFO("Started MTP2!\n");
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_STARTED);
}
if (sng_isup_init_mtp1()) {
SS7_CRITICAL("Failed to start MTP2\n");
SS7_CRITICAL("Failed to start MTP1\n");
return 1;
} else {
SS7_INFO("Started MTP1!\n");
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP1_STARTED);
}
if (ftmod_ss7_mtp1_gen_config()) {
SS7_CRITICAL("MTP1 General configuration FAILED!\n");
@@ -376,7 +382,7 @@ int ft_to_sngss7_cfg_all(void)
x++;
} /* while (x < (MAX_ISAPS)) */
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_STARTED)) {
x = 1;
while (x < (MAX_ISUP_INFS)) {
/* check if this link has been configured already */
@@ -913,13 +919,14 @@ int ftmod_ss7_mtp3_dlsap_config(int id)
#endif /* SDT2 */
cfg.t.cfg.s.snDLSAP.lnkId = 0; /* signalling link allocation procedure identity */
cfg.t.cfg.s.snDLSAP.lnkTstSLC = k->slc; /* link selection code for link test */
cfg.t.cfg.s.snDLSAP.tstLen = 6; /* link test pattern length */
cfg.t.cfg.s.snDLSAP.tst[0] = 'K'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[1] = 'O'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tstLen = 7; /* link test pattern length */
cfg.t.cfg.s.snDLSAP.tst[0] = 'S'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[1] = 'A'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[2] = 'N'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[3] = 'R'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[4] = 'A'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[5] = 'D'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[3] = 'G'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[4] = 'O'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[5] = 'M'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[6] = 'A'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.ssf = k->ssf; /* sub service field */
cfg.t.cfg.s.snDLSAP.dstProcId = k->mtp2ProcId; /* destination processor id */
cfg.t.cfg.s.snDLSAP.dstEnt = ENTSD; /* entity */
File diff suppressed because it is too large. Load diff
@@ -89,12 +89,13 @@ ftdm_status_t handle_olm_msg(uint32_t suInstId, uint32_t spInstId, uint32_t circ
ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt)
{
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
char nadi[2];
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
memset(nadi, '\0', sizeof(nadi));
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
char var[FTDM_DIGITS_LIMIT];
memset(var, '\0', sizeof(var));
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
@@ -209,12 +210,52 @@ 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);
sngss7_add_var(sngss7_info, "ss7_clg_nadi", nadi);
sprintf(var, "%d", siConEvnt->cgPtyNum.natAddrInd.val);
sngss7_add_var(sngss7_info, "ss7_clg_nadi", var);
sprintf(nadi, "%d", siConEvnt->cdPtyNum.natAddrInd.val);
sngss7_add_var(sngss7_info, "ss7_cld_nadi", nadi);
sprintf(var, "%d", siConEvnt->cdPtyNum.natAddrInd.val);
sngss7_add_var(sngss7_info, "ss7_cld_nadi", var);
/* Retrieve the Location Number if present (see ITU Q.763, 3.30) */
if (siConEvnt->cgPtyNum1.eh.pres) {
if (siConEvnt->cgPtyNum1.addrSig.pres) {
/* fill in the ss7 location address number */
copy_tknStr_from_sngss7(siConEvnt->cgPtyNum1.addrSig, var, siConEvnt->cgPtyNum1.oddEven);
sngss7_add_var(sngss7_info, "ss7_loc_digits", var);
}
if (siConEvnt->cgPtyNum1.scrnInd.pres) {
/* fill in the screening indication value */
sprintf(var, "%d", siConEvnt->cgPtyNum1.scrnInd.val);
sngss7_add_var(sngss7_info, "ss7_loc_screen_ind", var);
}
if (siConEvnt->cgPtyNum1.presRest.pres) {
/* fill in the presentation value */
sprintf(var, "%d", siConEvnt->cgPtyNum1.presRest.val);
sngss7_add_var(sngss7_info, "ss7_loc_pres_ind", var);
}
if (siConEvnt->cgPtyNum1.natAddrInd.pres) {
sprintf(var, "%d", siConEvnt->cgPtyNum1.natAddrInd.val);
sngss7_add_var(sngss7_info, "ss7_loc_nadi", var);
}
} else {
SS7_DEBUG_CHAN(ftdmchan, "No Location Number information in IAM%s\n", " ");
}
sprintf(var, "%d", sngss7_info->circuit->cic);
sngss7_add_var(sngss7_info, "ss7_cic", var);
sprintf(var, "%d", g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].spc );
sngss7_add_var(sngss7_info, "ss7_opc", var);
if (siConEvnt->callRef.callId.pres) {
ftdmchan->caller_data.call_reference = (unsigned int)siConEvnt->callRef.callId.val;
} else {
ftdmchan->caller_data.call_reference = 0;
}
if (sngss7_info->circuit->transparent_iam) {
sngss7_save_iam(ftdmchan, siConEvnt);
}
@@ -252,9 +293,9 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
case (FTDM_CHANNEL_STATE_HANGUP_COMPLETE):
handle_glare:
/* the core already has plans for this channel...glare */
SS7_INFO_CHAN(ftdmchan, "Got IAM on channel that is already inuse (state=%s|inuse=%d)...glare!\n",
SS7_INFO_CHAN(ftdmchan, "Got IAM on channel that is already inuse (state=%s|inuse=%c)...glare!\n",
ftdm_channel_state2str (ftdmchan->state),
ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE));
ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE) ? 'Y' : 'N');
/* save the info so that we can use it later on */
sngss7_info->glare.spInstId = spInstId;
@@ -401,6 +442,8 @@ ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circ
append_tknStr_from_sngss7(siCnStEvnt->subNum.addrSig,
ftdmchan->caller_data.dnis.digits,
siCnStEvnt->subNum.oddEven);
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Rx SAM (digits = %s)\n", sngss7_info->circuit->cic,
ftdmchan->caller_data.dnis.digits);
} else {
SS7_INFO_CHAN(ftdmchan,"No Called party (DNIS) information in SAM!%s\n", " ");
}
@@ -696,7 +739,7 @@ ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
* ITU Q.784 Test Number 3.8
* Collision of REL messages
*/
SS7_DEBUG_CHAN(ftdmchan, "Collision of REL messages. Rx REL while waiting for RLC.\n", " ");
SS7_DEBUG_CHAN(ftdmchan, "Collision of REL messages. Rx REL while waiting for RLC.%s\n", " ");
if (sngss7_test_ckt_flag(sngss7_info, FLAG_LOCAL_REL) &&
!sngss7_test_ckt_flag (sngss7_info, FLAG_REMOTE_REL)) {
/* locally requested hangup completed, wait for remote RLC */
@@ -1639,8 +1682,8 @@ ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
ftdm_mutex_lock(ftdmchan->mutex);
/* check if the channel is blocked */
if (!(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX))) {
SS7_WARN("Received UBL on circuit that is not blocked!\n");
if (!(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) && !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) {
SS7_WARN("Received UBL on circuit that is not blocked! span= %d, chan= %d , flag = %x \n", g_ftdm_sngss7_data.cfg.isupCkt[circuit].span, g_ftdm_sngss7_data.cfg.isupCkt[circuit].chan,sngss7_info->blk_flags );
}
/* throw the unblock flag */
@@ -1648,6 +1691,8 @@ ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* clear the block flag */
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX_DN);
/* set the channel to suspended state */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
@@ -1688,14 +1733,6 @@ ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
DECODE_LCC_EVENT(evntType));
}
/* lock the channel */
ftdm_mutex_lock(ftdmchan->mutex);
/* KONRAD FIX ME */
/* unlock the channel again before we exit */
ftdm_mutex_unlock(ftdmchan->mutex);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return FTDM_SUCCESS;
}
@@ -1860,7 +1897,7 @@ ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* go to DOWN */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
} else {
SS7_ERROR("Received RSC-RLC but we're not waiting on a RSC-RLC on CIC #, dropping\n", sngss7_info->circuit->cic);
SS7_ERROR("Received RSC-RLC but we're not waiting on a RSC-RLC on CIC #%d, dropping\n", sngss7_info->circuit->cic);
}
break;
@@ -2449,6 +2486,8 @@ ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/**********************************************************************/
case 0: /* maintenance oriented */
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN);
break;
/**********************************************************************/
case 1: /* hardware failure oriented */
@@ -486,47 +486,47 @@ void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint
g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic);
}
x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
x = (g_ftdm_sngss7_data.cfg.procId * MAX_CIC_MAP_LENGTH) + 1;
while ((g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) &&
(g_ftdm_sngss7_data.cfg.isupCkt[x].id < ((g_ftdm_sngss7_data.cfg.procId +1) * 1000))) {
/**********************************************************************/
(g_ftdm_sngss7_data.cfg.isupCkt[x].id < ((g_ftdm_sngss7_data.cfg.procId + 1) * MAX_CIC_MAP_LENGTH))) {
/**********************************************************************/
/* confirm this is a voice channel and not a gap/sig (no ftdmchan there) */
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type != SNG_CKT_VOICE) goto move_along;
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) {
/* compare the intfIds */
if (g_ftdm_sngss7_data.cfg.isupCkt[x].infId == intfId) {
/* we have a match, setup the pointers to the correct values */
circuit = x;
/* compare the intfIds */
if (g_ftdm_sngss7_data.cfg.isupCkt[x].infId == intfId) {
/* we have a match, setup the pointers to the correct values */
circuit = x;
/* confirm that the circuit is active on our side otherwise move to the next circuit */
if (!sngss7_test_flag(&g_ftdm_sngss7_data.cfg.isupCkt[circuit], SNGSS7_ACTIVE)) {
SS7_DEBUG("[CIC:%d]Rx %s but circuit is not active yet, skipping!\n",
g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic,
DECODE_LCC_EVENT(evntType));
x++;
continue;
}
/* confirm that the circuit is active on our side otherwise move to the next circuit */
if (!sngss7_test_flag(&g_ftdm_sngss7_data.cfg.isupCkt[circuit], SNGSS7_ACTIVE)) {
SS7_DEBUG("[CIC:%d]Rx %s but circuit is not active yet, skipping!\n",
g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic,
DECODE_LCC_EVENT(evntType));
continue;
}
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
/* bounce out of the loop */
break;
}
}
/* bounce out of the loop */
break;
} /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].intfId == intfId) */
move_along:
/* move along ... nothing to see here */
x++;
/**********************************************************************/
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
/**********************************************************************/
}
/* check if we found any circuits that are on the intfId, drop the message
* if none are found
*/
if (ftdmchan == NULL) goto sta_ind_end;
* if none are found */
if (!ftdmchan) {
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
break;
/**************************************************************************/
@@ -544,7 +544,6 @@ move_along:
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
break;
/**************************************************************************/
} /* switch (evntType) */
@@ -571,9 +570,6 @@ move_along:
/* enqueue this event */
ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
sta_ind_end:
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
/******************************************************************************/
@@ -31,6 +31,7 @@
* SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* INCLUDE ********************************************************************/
#include "ftmod_sangoma_ss7_main.h"
/******************************************************************************/
@@ -279,7 +280,7 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtp2Link[x].name);
}
ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s %s : %d\n",
ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s %s : %s\n",
buf,
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_DISC_REASON(sta->t.usta.evntParm[1]));
@@ -353,6 +354,8 @@ void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta)
char buf[50];
int x = 1;
SS7_RELAY_DBG_FUN(handle_sng_mtp3_alarm);
memset(buf, '\0', sizeof(buf));
switch (sta->hdr.elmId.elmnt) {
@@ -492,6 +495,8 @@ void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
char tmp[25];
char *p = NULL;
int x = 0;
SS7_RELAY_DBG_FUN(handle_sng_isup_alarm);
/* initalize the msg variable to NULLs */
memset(&msg[0], '\0', sizeof(&msg));
@@ -502,7 +507,6 @@ void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
return;
}
/* point p to the first spot in msg */
p = &msg[0];
@@ -742,6 +746,7 @@ void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta)
{
SS7_RELAY_DBG_FUN(handle_sng_cc_alarm);
return;
} /* handle_cc_alarm */
@@ -749,6 +754,7 @@ void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta)
void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta)
{
SS7_RELAY_DBG_FUN(handle_sng_relay_alarm);
switch (sta->hdr.elmId.elmnt) {
/**************************************************************************/
@@ -60,6 +60,7 @@ static ftdm_status_t ftdm_sangoma_ss7_stop (ftdm_span_t * span);
static ftdm_status_t ftdm_sangoma_ss7_start (ftdm_span_t * span);
/******************************************************************************/
/* STATE MAP ******************************************************************/
ftdm_state_map_t sangoma_ss7_state_map = {
{
@@ -281,7 +282,37 @@ ftdm_state_map_t sangoma_ss7_state_map = {
}
};
/******************************************************************************/
static void handle_hw_alarm(ftdm_event_t *e)
{
sngss7_chan_data_t *ss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
int x = 0;
ftdm_assert(e != NULL, "Null event!\n");
for (x = (g_ftdm_sngss7_data.cfg.procId * MAX_CIC_MAP_LENGTH) + 1; g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0; x++) {
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) {
ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
ftdmchan = ss7_info->ftdmchan;
if (e->channel->span_id == ftdmchan->physical_span_id &&
e->channel->chan_id == ftdmchan->physical_chan_id) {
if (e->enum_id == FTDM_OOB_ALARM_TRAP) {
sngss7_set_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX);
if (ftdmchan->state != FTDM_CHANNEL_STATE_SUSPENDED) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
}
} else {
sngss7_set_ckt_blk_flag(ss7_info, FLAG_GRP_HW_UNBLK_TX);
sngss7_clear_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX);
if (ftdmchan->state != FTDM_CHANNEL_STATE_SUSPENDED) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
}
}
}
}
}
}
/* MONITIOR THREADS ***********************************************************/
static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
@@ -293,6 +324,9 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
sngss7_event_data_t *sngss7_event = NULL;
sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
int b_alarm_test = 1;
sngss7_chan_data_t *ss7_info=NULL;
ftdm_log (FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u started.\n", ftdmspan->span_id);
/* set IN_THREAD flag so that we know this thread is running */
@@ -311,6 +345,30 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
}
while (ftdm_running () && !(ftdm_test_flag (ftdmspan, FTDM_SPAN_STOP_THREAD))) {
int x = 0;
if (b_alarm_test) {
b_alarm_test = 0;
for (x = (g_ftdm_sngss7_data.cfg.procId * MAX_CIC_MAP_LENGTH) + 1;
g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0; x++) {
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) {
ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
ftdmchan = ss7_info->ftdmchan;
if (!ftdmchan) {
continue;
}
if (ftdmchan->alarm_flags != 0) { /* we'll send out block */
sngss7_set_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX );
} else { /* we'll send out reset */
sngss7_clear_ckt_blk_flag( ss7_info, FLAG_GRP_HW_BLOCK_TX );
sngss7_clear_ckt_blk_flag( ss7_info, FLAG_GRP_HW_BLOCK_TX_DN );
sngss7_set_ckt_blk_flag (ss7_info, FLAG_GRP_HW_UNBLK_TX);
}
}
usleep(50);
}
ftdmchan = NULL;
}
/* check the channel state queue for an event*/
switch ((ftdm_interrupt_multiple_wait(ftdm_sangoma_ss7_int, 2, 100))) {
@@ -388,7 +446,11 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
switch (ftdm_span_poll_event(ftdmspan, 0, NULL)) {
/**********************************************************************/
case FTDM_SUCCESS:
while (ftdm_span_next_event(ftdmspan, &event) == FTDM_SUCCESS);
while (ftdm_span_next_event(ftdmspan, &event) == FTDM_SUCCESS) {
if (event->e_type == FTDM_EVENT_OOB) {
handle_hw_alarm(event);
}
}
break;
/**********************************************************************/
case FTDM_TIMEOUT:
@@ -530,6 +592,11 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
i++;
}
/* kill t10 if active */
if (sngss7_info->t10.hb_timer_id) {
ftdm_sched_cancel_timer (sngss7_info->t10.sched, sngss7_info->t10.hb_timer_id);
}
/* check if the end of pulsing (ST) character has arrived or the right number of digits */
if (ftdmchan->caller_data.dnis.digits[i-1] == 'F') {
SS7_DEBUG_CHAN(ftdmchan, "Received the end of pulsing character %s\n", "");
@@ -551,7 +618,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
} else {
/* if we are coming from idle state then we have already been here once before */
if (ftdmchan->last_state != FTDM_CHANNEL_STATE_IDLE) {
SS7_INFO_CHAN(ftdmchan,"Received %d out of %d so far: %s...starting T35\n",
SS7_INFO_CHAN(ftdmchan, "Received %d out of %d so far: %s...starting T35\n",
i,
sngss7_info->circuit->min_digits,
ftdmchan->caller_data.dnis.digits);
@@ -566,7 +633,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
SS7_ERROR ("Unable to schedule timer, hanging up call!\n");
ftdmchan->caller_data.hangup_cause = 41;
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE;
/* set the flag to indicate this hangup is started from the local side */
sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL);
@@ -574,9 +641,29 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* end the call */
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
} /* if (ftdm_sched_timer(sngss7_info->t35.sched, */
} /* if (ftdmchan->last_state != FTDM_CHANNEL_STATE_IDLE) */
} /* checking ST/#digits */
}
}
/* start ISUP t10 */
if (ftdm_sched_timer (sngss7_info->t10.sched,
"t10",
sngss7_info->t10.beat,
sngss7_info->t10.callback,
&sngss7_info->t10,
&sngss7_info->t10.hb_timer_id)) {
SS7_ERROR ("Unable to schedule timer, hanging up call!\n");
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE;
/* set the flag to indicate this hangup is started from the local side */
sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL);
/* end the call */
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
}
}
break;
@@ -656,10 +743,14 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
/* inform the user there is media avai */
sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_PROGRESS_MEDIA);
} else {
if (!sngss7_test_ckt_flag(sngss7_info, FLAG_SENT_ACM)) {
sngss7_set_ckt_flag(sngss7_info, FLAG_SENT_ACM);
ft_to_sngss7_acm(ftdmchan);
}
ft_to_sngss7_cpg(ftdmchan);
}
/* nothing to do at this time */
break;
/**************************************************************************/
case FTDM_CHANNEL_STATE_UP: /*call is accpeted...both incoming and outgoing */
@@ -751,9 +842,18 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
if (sngss7_test_ckt_flag (sngss7_info, FLAG_REMOTE_REL)) {
/* check if this hangup is from a tx RSC */
if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX)) {
/* go to RESTART State until RSCa is received */
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
if (!sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_SENT)) {
ft_to_sngss7_rsc (ftdmchan);
sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_SENT);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
} else if (sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP)) {
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
} else {
/* go to RESTART State until RSCa is received */
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
}
} else {
/* if the hangup is from a rx RSC, rx GRS, or glare don't sent RLC */
if (!(sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_RX)) &&
@@ -844,7 +944,9 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* check if we came from reset (aka we just processed a reset) */
if ((ftdmchan->last_state == FTDM_CHANNEL_STATE_RESTART) ||
(ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED)) {
(ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) ||
(ftdmchan->last_state == FTDM_CHANNEL_STATE_HANGUP_COMPLETE)) {
/* check if reset flags are up indicating there is more processing to do yet */
if (!(sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX)) &&
@@ -949,9 +1051,12 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
if ((sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX)) &&
!(sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_SENT))) {
/* send a reset request */
ft_to_sngss7_rsc (ftdmchan);
sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_SENT);
/* don't send out reset before finished hanging up if I'm in-use. */
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) {
/* send a reset request */
ft_to_sngss7_rsc (ftdmchan);
sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_SENT);
}
} /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX)) */
@@ -1102,16 +1207,97 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* clear the unblock flag */
sngss7_clear_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX);
/* bring the sig status up */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
/* not bring the cic up if there is a hardware block */
if( !sngss7_test_ckt_blk_flag(sngss7_info, (FLAG_GRP_HW_BLOCK_TX | FLAG_GRP_HW_BLOCK_TX_DN) ) ) {
/* bring the sig status up */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
/* send a uba */
ft_to_sngss7_uba (ftdmchan);
/* send a uba */
ft_to_sngss7_uba (ftdmchan);
}
/* check the last state and return to it to allow the call to finish */
goto suspend_goto_last;
}
/**********************************************************************/
/* hardware block/unblock tx */
if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_GRP_HW_BLOCK_TX ) &&
!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX_DN )) {
SS7_DEBUG_CHAN(ftdmchan, "Processing FLAG_GRP_HW_BLOCK_TX flag %s\n", "");
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN);
/* dont send block again if the channel is already blocked by maintenance */
if( !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX) &&
!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX_DN)
) {
ft_to_sngss7_blo(ftdmchan);
}
sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX_DN);
goto suspend_goto_last;
}
if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_UNBLK_TX)) {
SS7_DEBUG_CHAN(ftdmchan, "Processing FLAG_GRP_HW_UNBLK_TX flag %s\n", "");
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX_DN);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_UNBLK_TX);
/* do not set the channel up if it's blocked by blo/cgb command OR blocked by receiving blo/cgb */
if (!sngss7_test_ckt_blk_flag(sngss7_info, ( FLAG_CKT_MN_BLOCK_TX
| FLAG_CKT_MN_BLOCK_TX
| FLAG_GRP_MN_BLOCK_TX
| FLAG_GRP_MN_BLOCK_TX_DN
| FLAG_CKT_MN_BLOCK_RX
| FLAG_CKT_MN_BLOCK_RX_DN
| FLAG_GRP_MN_BLOCK_RX
| FLAG_GRP_MN_BLOCK_RX_DN
)
)
) {
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
ft_to_sngss7_ubl(ftdmchan);
}
goto suspend_goto_last;
}
#if 0
//jz: there is no such thing of "remote hw block". for receiver, there are only block and unblock
/**********************************************************************/
// jz: hardware block/unblock rx
if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_GRP_HW_BLOCK_RX ) &&
!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX_DN )) {
SS7_DEBUG_CHAN(ftdmchan, "Processing FLAG_GRP_HW_BLOCK_RX flag %s\n", "");
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN);
ft_to_sngss7_bla(ftdmchan);
sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX_DN);
goto suspend_goto_last;
}
if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_GRP_HW_UNBLK_RX )){
SS7_DEBUG_CHAN(ftdmchan, "Processing FLAG_GRP_HW_UNBLK_RX flag %s\n", "");
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX_DN);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_UNBLK_RX);
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
ft_to_sngss7_uba(ftdmchan);
goto suspend_goto_last;
}
#endif
/**********************************************************************/
if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX) &&
!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX_DN)) {
@@ -1142,11 +1328,14 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* clear the unblock flag */
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX);
/* bring the sig status up */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
/* not bring the cic up if there is a hardware block */
if (!sngss7_test_ckt_blk_flag(sngss7_info, (FLAG_GRP_HW_BLOCK_TX | FLAG_GRP_HW_BLOCK_TX_DN))) {
/* bring the sig status up */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
/* send a ubl */
ft_to_sngss7_ubl (ftdmchan);
/* send a ubl */
ft_to_sngss7_ubl(ftdmchan);
}
/* check the last state and return to it to allow the call to finish */
goto suspend_goto_last;
@@ -1624,32 +1813,37 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_ss7_unload)
ftdm_log (FTDM_LOG_INFO, "Starting ftmod_sangoma_ss7 unload...\n");
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_STARTED)) {
sng_isup_free_cc();
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC);
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_STARTED);
}
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_STARTED)) {
ftmod_ss7_shutdown_isup();
sng_isup_free_isup();
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP);
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_STARTED);
}
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3_STARTED)) {
ftmod_ss7_shutdown_mtp3();
sng_isup_free_mtp3();
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3);
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3_STARTED);
}
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_STARTED)) {
ftmod_ss7_shutdown_mtp2();
sng_isup_free_mtp2();
sng_isup_free_mtp1();
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2);
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_STARTED);
}
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY)) {
/* go through all the relays channels and configure it */
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP1_STARTED)) {
sng_isup_free_mtp1();
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP1_STARTED);
}
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY_STARTED)) {
/* go through all the relays channels and disable them */
x = 1;
while (x < (MAX_RELAY_CHANNELS)) {
/* check if this relay channel has been configured already */
@@ -1658,24 +1852,28 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_ss7_unload)
/* send the specific configuration */
if (ftmod_ss7_disable_relay_channel(x)) {
SS7_CRITICAL("Relay Channel %d disable failed!\n", x);
return 1;
/* jz: dont leave like this
* return 1;
* */
} else {
SS7_INFO("Relay Channel %d disable DONE!\n", x);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.relay[x].flags &= !SNGSS7_CONFIGURED;
g_ftdm_sngss7_data.cfg.relay[x].flags &= ~(SNGSS7_CONFIGURED);
} /* if !SNGSS7_CONFIGURED */
x++;
} /* while (x < (MAX_RELAY_CHANNELS)) */
ftmod_ss7_shutdown_relay();
sng_isup_free_relay();
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY);
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY_STARTED);
}
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM_STARTED)) {
sng_isup_free_sm();
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM_STARTED);
}
sng_isup_free_gen();
@@ -51,7 +51,7 @@
/* DEFINES ********************************************************************/
#define MAX_NAME_LEN 25
#define MAX_PATH 255
#define MAX_PATH 4096
#define MAX_CIC_LENGTH 5
#define MAX_CIC_MAP_LENGTH 1000
@@ -64,12 +64,10 @@
(switchtype == LSI_SW_ANS92) || \
(switchtype == LSI_SW_ANS95)
typedef struct ftdm2trillium
{
typedef struct ftdm2trillium {
uint8_t ftdm_val;
uint8_t trillium_val;
}ftdm2trillium_t;
} ftdm2trillium_t;
typedef enum {
SNGSS7_CON_IND_EVENT = 0,
@@ -290,7 +288,6 @@ typedef struct sng_isup_intf {
uint32_t ssf;
uint32_t isap;
uint16_t t4;
uint32_t t10;
uint32_t t11;
uint32_t t18;
uint32_t t19;
@@ -346,6 +343,7 @@ typedef struct sng_isup_ckt {
uint8_t transparent_iam;
void *obj;
uint16_t t3;
uint32_t t10;
uint16_t t12;
uint16_t t13;
uint16_t t14;
@@ -473,6 +471,7 @@ typedef struct sngss7_chan_data {
void *raw_data; /* send on next sigevent */
sngss7_glare_data_t glare;
sngss7_timer_data_t t35;
sngss7_timer_data_t t10;
sngss7_group_data_t rx_grs;
sngss7_group_data_t rx_gra;
sngss7_group_data_t tx_grs;
@@ -609,22 +608,20 @@ typedef enum {
"TX CKT BLK DN", \
"TX CKT UNBLK", \
"TX CKT UNBLK DN", \
"RX GRP MN BLK", \
"RX GRP MN BLK DN", \
"RX GRP MN UNBLK", \
"RX GRP MN UNBLK DN", \
"TX GRP MN BLK", \
"TX GRP MN BLK DN", \
"TX GRP MN UNBLK", \
"TX GRP MN UNBLK DN", \
"RX GRP HW BLK", \
"RX GRP HW BLK DN", \
"RX GRP HW UNBLK", \
"RX GRP HW UNBLK DN", \
"TX GRP HW BLK", \
"TX GRP HW BLK DN", \
"RX GRP MN BLK", \
"RX GRP MN BLK DN", \
"TX GRP MN BLK", \
"TX GRP MN BLK DN", \
"TX GRP HW UNBLK", \
"TX GRP HW UNBLK DN"
"TX GRP HW UNBLK DN", \
"TX GRP MN UNBLK", \
"TX GRP MN UNBLK DN", \
"RX GRP HW UNBLK", \
"RX GRP HW UNBLK DN"
FTDM_STR2ENUM_P(ftmod_ss7_blk_state2flag, ftmod_ss7_blk_flag2str, sng_ckt_block_flag_t)
/* valid for every cfg array except circuits */
@@ -636,13 +633,25 @@ typedef enum {
} sng_cfg_flag_t;
typedef enum {
SNGSS7_SM = (1 << 0),
SNGSS7_RY = (1 << 1),
SNGSS7_MTP1 = (1 << 2),
SNGSS7_MTP2 = (1 << 3),
SNGSS7_MTP3 = (1 << 4),
SNGSS7_ISUP = (1 << 5),
SNGSS7_CC = (1 << 6)
SNGSS7_SM_STARTED = (1 << 0),
SNGSS7_RY_PRESENT = (1 << 2),
SNGSS7_RY_STARTED = (1 << 3),
SNGSS7_MTP1_PRESENT = (1 << 4),
SNGSS7_MTP1_STARTED = (1 << 5),
SNGSS7_MTP2_PRESENT = (1 << 6),
SNGSS7_MTP2_STARTED = (1 << 7),
SNGSS7_MTP3_PRESENT = (1 << 8),
SNGSS7_MTP3_STARTED = (1 << 9),
SNGSS7_ISUP_PRESENT = (1 << 10),
SNGSS7_ISUP_STARTED = (1 << 11),
SNGSS7_CC_PRESENT = (1 << 12),
SNGSS7_CC_STARTED = (1 << 13),
} sng_task_flag_t;
/******************************************************************************/
@@ -739,6 +748,7 @@ int ftmod_ss7_isup_ckt_sta(uint32_t id, unsigned char *state);
/* in ftmod_sangoma_ss7_out.c */
void ft_to_sngss7_iam(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_acm(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_cpg (ftdm_channel_t *ftdmchan);
void ft_to_sngss7_anm(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_rel(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_rlc(ftdm_channel_t *ftdmchan);
@@ -878,6 +888,7 @@ ftdm_status_t sngss7_add_raw_data(sngss7_chan_data_t *sngss7_info, uint8_t* data
/* in ftmod_sangoma_ss7_timers.c */
void handle_isup_t35(void *userdata);
void handle_isup_t10(void *userdata);
/******************************************************************************/
@@ -1029,13 +1040,12 @@ if (ftdmchan->state == new_state) { \
#define sngss7_set_options(obj, option) ((obj)->options |= (option))
#ifdef SS7_PRODUCTION
# define SS7_ASSERT \
SS7_INFO_CHAN(ftdmchan,"Production Mode, continuing%s\n", "");
#ifdef SMG_RELAY_DBG
#define SS7_RELAY_DBG(a,...) printf(a"\n", ##__VA_ARGS__)
#define SS7_RELAY_DBG_FUN(a) printf(#a"\n")
#else
# define SS7_ASSERT \
SS7_ERROR_CHAN(ftdmchan, "Debugging Mode, ending%s\n", ""); \
*(int*)0=0;
#define SS7_RELAY_DBG(a, ...)
#define SS7_RELAY_DBG_FUN(a)
#endif
/******************************************************************************/
@@ -36,6 +36,8 @@
/******************************************************************************/
/* DEFINES ********************************************************************/
#define SNGSS7_EVNTINFO_IND_INBAND_AVAIL 0x03
/******************************************************************************/
/* GLOBALS ********************************************************************/
@@ -171,6 +173,7 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
acm.optBckCalInd.simpleSegmInd.pres = PRSNT_DEF;
acm.optBckCalInd.mlppUserInd.pres = PRSNT_DEF;
acm.optBckCalInd.usrNetIneractInd.pres = PRSNT_DEF;
acm.optBckCalInd.netExcDelInd.pres = PRSNT_DEF;
} /* if (sngss7_test_options(isup_intf, SNGSS7_ACM_OBCI_BITA)) */
/* send the ACM request to LibSngSS7 */
@@ -187,6 +190,31 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
return;
}
void ft_to_sngss7_cpg (ftdm_channel_t *ftdmchan)
{
SiCnStEvnt cpg;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
memset (&cpg, 0, sizeof (cpg));
cpg.evntInfo.eh.pres = PRSNT_NODEF;
cpg.evntInfo.evntInd.pres = PRSNT_NODEF;
cpg.evntInfo.evntInd.val = SNGSS7_EVNTINFO_IND_INBAND_AVAIL; /* Event Indicator = In-band info is now available */
cpg.evntInfo.evntPresResInd.pres = PRSNT_NODEF;
cpg.evntInfo.evntPresResInd.val = 0; /* Event presentation restricted indicator = no indication */
/* send the CPG request to LibSngSS7 */
sng_cc_con_status (1, sngss7_info->suInstId, sngss7_info->spInstId, sngss7_info->circuit->id, &cpg, PROGRESS);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "[CIC:%d]Tx CPG\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
@@ -49,7 +49,7 @@ ftdm_status_t handle_relay_disconnect(RyMngmt *sta);
static ftdm_status_t reconfig_all_ckts_for_relay(void);
static ftdm_status_t disable_all_ckts_for_relay(void);
static ftdm_status_t block_all_ckts_for_relay(uint32_t procId);
static ftdm_status_t unblock_all_ckts_for_relay(uint32_t procId);
/* static ftdm_status_t unblock_all_ckts_for_relay(uint32_t procId); */
static ftdm_status_t disable_all_sigs_for_relay(uint32_t procId);
static ftdm_status_t disble_all_mtp2_sigs_for_relay(void);
/******************************************************************************/
@@ -59,43 +59,26 @@ ftdm_status_t handle_relay_connect(RyMngmt *sta)
{
sng_relay_t *sng_relay = &g_ftdm_sngss7_data.cfg.relay[sta->t.usta.s.ryUpUsta.id];
/* test if this is the first time the channel comes up */
if (!sngss7_test_flag(sng_relay, SNGSS7_RELAY_INIT)) {
SS7_INFO("Relay Channel %d initial connection UP\n", sng_relay->id);
/* mark the channel as being up */
/* SS7_INFO("Relay Channel %d initial connection UP\n", sng_relay->id); */
sngss7_set_flag(sng_relay, SNGSS7_RELAY_INIT);
} else {
SS7_INFO("Relay Channel %d connection UP\n", sng_relay->id);
/* react based on type of channel */
switch (sng_relay->type) {
/******************************************************************/
case (LRY_CT_TCP_CLIENT):
/* reconfigure all ISUP ckts, since the main system would have lost all configs */
}
SS7_INFO("Relay Channel %d connection UP\n", sng_relay->id);
if (sng_relay->type == LRY_CT_TCP_CLIENT) {
if (!sngss7_test_flag(sng_relay, SNGSS7_RELAY_INIT)) {
if (reconfig_all_ckts_for_relay()) {
SS7_ERROR("Failed to reconfigure ISUP Ckts!\n");
/* we're done....this is very bad! */
}
break;
/******************************************************************/
case (LRY_CT_TCP_SERVER):
/* bring the sig links on the client system back up */
ftmod_ss7_enable_grp_mtp3Link(sta->t.usta.s.ryUpUsta.id);
/* unbloock the ckts on the client system */
unblock_all_ckts_for_relay(sta->t.usta.s.ryUpUsta.id);
break;
/******************************************************************/
default:
break;
/******************************************************************/
} /* switch (g_ftdm_sngss7_data.cfg.relay[sta->t.usta.s.ryUpUsta.id].type) */
} /* intial up? */
return FTDM_SUCCESS;
}
return FTDM_SUCCESS;
} else if (sng_relay->type == LRY_CT_TCP_SERVER) {
ftmod_ss7_enable_grp_mtp3Link(sta->t.usta.s.ryUpUsta.id);
/* unbloock the ckts on the client system */
return FTDM_SUCCESS;
}
return FTDM_FAIL;
}
/******************************************************************************/
@@ -300,7 +283,7 @@ ftdm_status_t disable_all_sigs_for_relay(uint32_t procId)
ftdm_status_t disble_all_mtp2_sigs_for_relay(void)
{
/* check if there is a local mtp2 link*/
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_STARTED)) {
SS7_INFO("Disalbing all mtp2 sig links on local system\n");
ftmod_ss7_disable_grp_mtp2Link(1);
@@ -310,6 +293,7 @@ ftdm_status_t disble_all_mtp2_sigs_for_relay(void)
}
#if 0
/******************************************************************************/
static ftdm_status_t unblock_all_ckts_for_relay(uint32_t procId)
{
@@ -345,6 +329,7 @@ static ftdm_status_t unblock_all_ckts_for_relay(uint32_t procId)
return FTDM_SUCCESS;
}
#endif
/******************************************************************************/
/* For Emacs:
@@ -319,7 +319,7 @@ ftdm_status_t copy_genNmb_from_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb
if (genNmb->nmbQual.pres == PRSNT_NODEF) {
snprintf(val, sizeof(val), "%d", genNmb->nmbQual.val);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number \"number qualifier\" \n", val);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number \"number qualifier\" \"%s\"\n", val);
sngss7_add_var(sngss7_info, "ss7_gn_numqual", val);
}
@@ -2454,7 +2454,7 @@ ftdm_status_t sngss7_save_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt)
goto done;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Compressed IAM size:%d\n", len);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Compressed IAM size:%lu\n", len);
/* Worst case: size will triple after url encode */
url_encoded_iam = ftdm_malloc(3*sizeof(*siConEvnt));
@@ -2468,10 +2468,10 @@ ftdm_status_t sngss7_save_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt)
/* URL encode buffer to that its safe to store it in a string */
ftdm_url_encode((const char*)compressed_iam, url_encoded_iam, len);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IAM variable length:%d\n", strlen(url_encoded_iam));
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IAM variable length:%"FTDM_SIZE_FMT"\n", strlen(url_encoded_iam));
if (strlen(url_encoded_iam) > g_ftdm_sngss7_data.cfg.transparent_iam_max_size) {
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "IAM variable length exceeds max size (len:%d max:%d) \n", strlen(url_encoded_iam), g_ftdm_sngss7_data.cfg.transparent_iam_max_size);
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "IAM variable length exceeds max size (len:%"FTDM_SIZE_FMT" max:%d) \n", strlen(url_encoded_iam), g_ftdm_sngss7_data.cfg.transparent_iam_max_size);
ret_val = FTDM_FAIL;
goto done;
}
@@ -2505,10 +2505,10 @@ ftdm_status_t sngss7_retrieve_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt
url_encoded_iam = ftdm_strdup(val);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IAM variable length:%d\n", strlen(val));
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IAM variable length:%"FTDM_SIZE_FMT"\n", strlen(val));
ftdm_url_decode(url_encoded_iam, &url_encoded_iam_len);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Compressed IAM size:%d\n", url_encoded_iam_len);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Compressed IAM size:%"FTDM_SIZE_FMT"\n", url_encoded_iam_len);
uncompressed_buffer = ftdm_malloc(sizeof(*siConEvnt));
ftdm_assert_return(uncompressed_buffer, FTDM_FAIL, "Failed to allocate buffer for uncompressed buffer\n");
@@ -2520,7 +2520,7 @@ ftdm_status_t sngss7_retrieve_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt
}
if (len != sizeof(*siConEvnt)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Incompatible IAM structure size (expected:%d size:%d)\n", sizeof(*siConEvnt), strlen(uncompressed_buffer));
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Incompatible IAM structure size (expected:%"FTDM_SIZE_FMT" size:%"FTDM_SIZE_FMT")\n", sizeof(*siConEvnt), strlen(uncompressed_buffer));
goto done;
}
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2009, Konrad Hammel <konrad@sangoma.com>
* Copyright (c) 2009, Sangoma Technologies
* Konrad Hammel <konrad@sangoma.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,6 +30,11 @@
* 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:
*
* Moises Silva <moy@sangoma.com>
*
*/
/* INCLUDE ********************************************************************/
@@ -56,25 +62,53 @@ void handle_isup_t35(void *userdata)
ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan;
/* now that we have the right channel...put a lock on it so no-one else can use it */
ftdm_mutex_lock(ftdmchan->mutex);
ftdm_channel_lock(ftdmchan);
/* Q.764 2.2.5 Address incomplete (T35 expiry action is hangup with cause 28 according to Table A.1/Q.764) */
SS7_ERROR("[Call-Control] Timer 35 expired on CIC = %d\n", sngss7_info->circuit->cic);
/* set the flag to indicate this hangup is started from the local side */
sngss7_set_ckt_flag(sngss7_info, FLAG_LOCAL_REL);
/* hang up on timer expiry */
ftdmchan->caller_data.hangup_cause = 28;
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_INVALID_NUMBER_FORMAT;
/* end the call */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
/* kill t10 if active */
if (sngss7_info->t10.hb_timer_id) {
ftdm_sched_cancel_timer (sngss7_info->t10.sched, sngss7_info->t10.hb_timer_id);
}
/*unlock*/
ftdm_mutex_unlock(ftdmchan->mutex);
ftdm_channel_unlock(ftdmchan);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void handle_isup_t10(void *userdata)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_timer_data_t *timer = userdata;
sngss7_chan_data_t *sngss7_info = timer->sngss7_info;
ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan;
ftdm_channel_lock(ftdmchan);
SS7_DEBUG("[Call-Control] Timer 10 expired on CIC = %d\n", sngss7_info->circuit->cic);
/* send the call to the user */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
ftdm_channel_unlock(ftdmchan);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
/******************************************************************************/
/* For Emacs:
* Local Variables:
@@ -62,6 +62,7 @@ sng_switch_type_t sng_switch_type_map[] =
{ 1, "india" , LSI_SW_INDIA , LSI_SW_INDIA },
{ 1, "uk" , LSI_SW_UK , LSI_SW_UK },
{ 1, "russia" , LSI_SW_RUSSIA , LSI_SW_RUSSIA },
{ 1, "china" , LSI_SW_CHINA , LSI_SW_CHINA },
{ 0, "", 0, 0 },
};
@@ -127,6 +128,7 @@ typedef struct sng_ccSpan
uint8_t itx_auto_reply;
uint8_t transparent_iam;
uint32_t t3;
uint32_t t10;
uint32_t t12;
uint32_t t13;
uint32_t t14;
@@ -1570,11 +1572,6 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
sng_isap.t9 = atoi(parm->val);
SS7_DEBUG("Found isup t9 = %d\n",sng_isap.t9);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "isup.t10")) {
/**********************************************************************/
sng_isup.t10 = atoi(parm->val);
SS7_DEBUG("Found isup t10 = %d\n",sng_isup.t10);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "isup.t11")) {
/**********************************************************************/
sng_isup.t11 = atoi(parm->val);
@@ -1965,6 +1962,10 @@ static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span)
/**********************************************************************/
sng_ccSpan.t3 = atoi(parm->val);
SS7_DEBUG("Found isup t3 = %d\n", sng_ccSpan.t3);
} else if (!strcasecmp(parm->var, "isup.t10")) {
/**********************************************************************/
sng_ccSpan.t10 = atoi(parm->val);
SS7_DEBUG("Found isup t10 = %d\n", sng_ccSpan.t10);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "isup.t12")) {
/**********************************************************************/
@@ -2082,7 +2083,7 @@ static int ftmod_ss7_fill_in_relay_channel(sng_relay_t *relay_channel)
relay_channel->port,
relay_channel->procId,
relay_channel->id);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY_PRESENT);
} else {
relay_channel->id = i;
SS7_DEBUG("found existing relay channel on type:%d, hostname:%s, port:%d, procId:%d, id = %d\n",
@@ -2116,7 +2117,7 @@ static int ftmod_ss7_fill_in_mtp1_link(sng_mtp1_link_t *mtp1Link)
/* check if this id value has been used already */
if (g_ftdm_sngss7_data.cfg.mtp1Link[i].id == 0) {
SS7_DEBUG("Found new MTP1 Link: id=%d, name=%s\n", mtp1Link->id, mtp1Link->name);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP1);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP1_PRESENT);
} else {
SS7_DEBUG("Found an existing MTP1 Link: id=%d, name=%s (old name=%s)\n",
mtp1Link->id,
@@ -2142,7 +2143,7 @@ static int ftmod_ss7_fill_in_mtp2_link(sng_mtp2_link_t *mtp2Link)
/* check if this id value has been used already */
if (g_ftdm_sngss7_data.cfg.mtp2Link[i].id == 0) {
SS7_DEBUG("Found new MTP2 Link: id=%d, name=%s\n", mtp2Link->id, mtp2Link->name);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_PRESENT);
} else {
SS7_DEBUG("Found an existing MTP2 Link: id=%d, name=%s (old name=%s)\n",
mtp2Link->id,
@@ -2219,7 +2220,7 @@ static int ftmod_ss7_fill_in_mtp3_link(sng_mtp3_link_t *mtp3Link)
/* check if this id value has been used already */
if (g_ftdm_sngss7_data.cfg.mtp3Link[i].id == 0) {
SS7_DEBUG("Found new MTP3 Link: id=%d, name=%s\n", mtp3Link->id, mtp3Link->name);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3_PRESENT);
} else {
SS7_DEBUG("Found an existing MTP3 Link: id=%d, name=%s (old name=%s)\n",
mtp3Link->id,
@@ -2560,7 +2561,7 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
/* check if this id value has been used already */
if (g_ftdm_sngss7_data.cfg.isupIntf[i].id == 0) {
SS7_DEBUG("Found new ISUP Interface: id=%d, name=%s\n", sng_isup->id, sng_isup->name);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_PRESENT);
} else {
SS7_DEBUG("Found an existing ISUP Interface: id=%d, name=%s (old name=%s)\n",
sng_isup->id,
@@ -2584,11 +2585,6 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
} else {
g_ftdm_sngss7_data.cfg.isupIntf[i].t4 = 3000;
}
if (sng_isup->t10 != 0) {
g_ftdm_sngss7_data.cfg.isupIntf[i].t10 = sng_isup->t10;
} else {
g_ftdm_sngss7_data.cfg.isupIntf[i].t10 = 50;
}
if (sng_isup->t11 != 0) {
g_ftdm_sngss7_data.cfg.isupIntf[i].t11 = sng_isup->t11;
} else {
@@ -2908,7 +2904,7 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
g_ftdm_sngss7_data.cfg.isupCkt[x].type = SNG_CKT_VOICE;
/* throw the flag to indicate that we need to start call control */
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_PRESENT);
}
if (timeslot.channel) {
@@ -2935,6 +2931,11 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
} else {
g_ftdm_sngss7_data.cfg.isupCkt[x].t3 = ccSpan->t3;
}
if (ccSpan->t10 == 0) {
g_ftdm_sngss7_data.cfg.isupCkt[x].t10 = 50;
} else {
g_ftdm_sngss7_data.cfg.isupCkt[x].t10 = ccSpan->t10;
}
if (ccSpan->t12 == 0) {
g_ftdm_sngss7_data.cfg.isupCkt[x].t12 = 300;
} else {
@@ -2966,9 +2967,10 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
g_ftdm_sngss7_data.cfg.isupCkt[x].t17 = ccSpan->t17;
}
if (ccSpan->t35 == 0) {
g_ftdm_sngss7_data.cfg.isupCkt[x].t17 = 170;
/* Q.764 2.2.5 Address incomplete (T35 is 15-20 seconds according to Table A.1/Q.764) */
g_ftdm_sngss7_data.cfg.isupCkt[x].t35 = 170;
} else {
g_ftdm_sngss7_data.cfg.isupCkt[x].t17 = ccSpan->t35;
g_ftdm_sngss7_data.cfg.isupCkt[x].t35 = ccSpan->t35;
}
if (ccSpan->tval == 0) {
g_ftdm_sngss7_data.cfg.isupCkt[x].tval = 10;
@@ -3062,12 +3064,18 @@ static int ftmod_ss7_fill_in_circuits(sng_span_t *sngSpan)
ftdmchan->call_data = ss7_info;
/* prepare the timer structures */
ss7_info->t35.sched = ((sngss7_span_data_t *)(ftdmspan->signal_data))->sched;
ss7_info->t35.sched = ((sngss7_span_data_t *)(ftdmspan->signal_data))->sched;
ss7_info->t35.counter = 1;
ss7_info->t35.beat = (isupCkt->t35) * 100; /* beat is in ms, t35 is in 100ms */
ss7_info->t35.beat = (isupCkt->t35) * 100; /* beat is in ms, t35 is in 100ms */
ss7_info->t35.callback = handle_isup_t35;
ss7_info->t35.sngss7_info = ss7_info;
ss7_info->t10.sched = ((sngss7_span_data_t *)(ftdmspan->signal_data))->sched;
ss7_info->t10.counter = 1;
ss7_info->t10.beat = (isupCkt->t10) * 100; /* beat is in ms, t10 is in 100ms */
ss7_info->t10.callback = handle_isup_t10;
ss7_info->t10.sngss7_info = ss7_info;
/**************************************************************************/
} /* for (i == 1; i < ftdmspan->chan_count; i++) */
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
+45 -19
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,9 +36,9 @@
* David Yat Sin <davidy@sangoma.com>
* Nenad Corbic <ncorbic@sangoma.com>
* Arnaldo Pereira <arnaldo@sangoma.com>
* Gideon Sadan <gsadan@sangoma.com>
*
*/
*/
#ifdef WP_DEBUG_IO
#define _BSD_SOURCE
#include <syscall.h>
@@ -121,6 +121,16 @@ FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event);
FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event);
FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event);
static void wp_swap16(char *data, int datalen)
{
int i = 0;
uint16_t *samples = (uint16_t *)data;
for (i = 0; i < datalen/2; i++) {
uint16_t sample = ((samples[i] & 0x00FF) << 8) | ((samples[i] & 0xFF00) >> 8);
samples[i] = sample;
}
}
/**
* \brief Poll for event on a wanpipe socket
* \param fd Wanpipe socket descriptor
@@ -305,11 +315,20 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
err = sangoma_tdm_get_hw_coding(chan->sockfd, &tdm_api);
if (tdm_api.wp_tdm_cmd.hw_tdm_coding) {
chan->native_codec = chan->effective_codec = FTDM_CODEC_ALAW;
} else {
chan->native_codec = chan->effective_codec = FTDM_CODEC_ULAW;
}
if ((span->trunk_type == FTDM_TRUNK_GSM) && (chan->type == FTDM_CHAN_TYPE_B)) {
chan->native_codec = FTDM_CODEC_SLIN;
chan->native_interval = 20;
chan->packet_len = 320;
}
err = sangoma_tdm_get_hw_dtmf(chan->sockfd, &tdm_api);
if (err > 0) {
@@ -580,8 +599,9 @@ static FIO_OPEN_FUNCTION(wanpipe_open)
ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL);
ftdmchan->effective_interval = ftdmchan->native_interval = wp_globals.codec_ms;
ftdmchan->packet_len = ftdmchan->native_interval * 8;
/* The packet len will depend on the codec and interval */
ftdmchan->packet_len = ftdmchan->native_interval * ((ftdmchan->native_codec==FTDM_CODEC_SLIN) ? 16 : 8);
if (wp_globals.txqueue_size > 0) {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &wp_globals.txqueue_size);
}
@@ -772,6 +792,7 @@ static FIO_COMMAND_FUNCTION(wanpipe_command)
case FTDM_COMMAND_SET_INTERVAL:
{
err=sangoma_tdm_set_usr_period(ftdmchan->sockfd, &tdm_api, FTDM_COMMAND_OBJ_INT);
ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8);
}
break;
@@ -793,7 +814,7 @@ static FIO_COMMAND_FUNCTION(wanpipe_command)
FTDM_COMMAND_OBJ_INT = wanpipe_swap_bits(rbsbits);
}
#else
// does sangoma_tdm_read_rbs is available here?
/* is sangoma_tdm_read_rbs available here? */
FTDM_COMMAND_OBJ_INT = ftdmchan->rx_cas_bits;
#endif
}
@@ -885,17 +906,11 @@ static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *t
}
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_DEBUG, "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) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet write stats: Tx queue len: %d, Tx queue size: %d, Tx idle: %d\n",
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet write stats: Tx queue len: %d, Tx queue size: %d, Tx idle: %"FTDM_UINT64_FMT"\n",
ftdmchan->iostats.tx.queue_len,
ftdmchan->iostats.tx.queue_size,
ftdmchan->iostats.tx.idle_packets);
@@ -941,11 +956,11 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx
}
if (ftdmchan->iostats.rx.queue_len >= (0.8 * ftdmchan->iostats.rx.queue_size)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Rx Queue length exceeded 80% threshold (%d/%d)\n",
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Rx Queue length exceeded 80%% threshold (%d/%d)\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
} else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Rx Queue length reduced 80% threshold (%d/%d)\n",
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Rx Queue length reduced 80%% threshold (%d/%d)\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
}
@@ -975,12 +990,15 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx
* \param datalen Size of data buffer
* \return Success, failure or timeout
*/
static FIO_READ_FUNCTION(wanpipe_read)
{
int rx_len = 0;
int rq_len = (int)*datalen;
wp_tdm_api_rx_hdr_t hdrframe;
#ifdef WP_DEBUG_IO
wp_channel_t *wchan = ftdmchan->io_data;
ftdm_time_t time_diff = 0;
@@ -1040,6 +1058,10 @@ static FIO_READ_FUNCTION(wanpipe_read)
wanpipe_read_stats(ftdmchan, &hdrframe);
}
if ((ftdmchan->type == FTDM_CHAN_TYPE_B) && (ftdmchan->span->trunk_type == FTDM_TRUNK_GSM)) {
wp_swap16(data, *datalen);
}
return FTDM_SUCCESS;
}
@@ -1056,6 +1078,10 @@ static FIO_WRITE_FUNCTION(wanpipe_write)
int err = 0;
wp_tdm_api_tx_hdr_t hdrframe;
if ((ftdmchan->type == FTDM_CHAN_TYPE_B) && (ftdmchan->span->trunk_type == FTDM_TRUNK_GSM)) {
wp_swap16(data, *datalen);
}
/* Do we even need the headerframe here? on windows, we don't even pass it to the driver */
memset(&hdrframe, 0, sizeof(hdrframe));
if (*datalen == 0) {
@@ -1490,10 +1516,10 @@ static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fc
if (fchan->dtmfdetect.duration_ms) {
ftdm_time_t diff = ftdm_current_time_in_ms() - fchan->dtmfdetect.start_time;
if (diff > fchan->dtmfdetect.duration_ms) {
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Queuing wanpipe DTMF: %c (duration:%d min:%d)\n", tmp_dtmf[0], diff, fchan->dtmfdetect.duration_ms);
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Queuing wanpipe DTMF: %c (duration:%"FTDM_TIME_FMT" min:%d)\n", tmp_dtmf[0], diff, fchan->dtmfdetect.duration_ms);
ftdm_channel_queue_dtmf(fchan, tmp_dtmf);
} else {
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Ignoring wanpipe DTMF: %c (duration:%d min:%d)\n", tmp_dtmf[0], diff, fchan->dtmfdetect.duration_ms);
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Ignoring wanpipe DTMF: %c (duration:%"FTDM_TIME_FMT" min:%d)\n", tmp_dtmf[0], diff, fchan->dtmfdetect.duration_ms);
}
} else if (!fchan->dtmfdetect.trigger_on_start) {
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Queuing wanpipe DTMF: %c\n", tmp_dtmf[0]);
@@ -1591,7 +1617,7 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
ftdm_clear_flag_locked(span->channels[i], FTDM_CHANNEL_FLASH);
ftdm_set_flag_locked(span->channels[i], FTDM_CHANNEL_OFFHOOK);
event_id = FTDM_OOB_OFFHOOK;
ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "Diff since last event = %llums, delivering %s now\n", diff, ftdm_oob_event2str(event_id));
ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "Diff since last event = %"FTDM_TIME_FMT" ms, delivering %s now\n", diff, ftdm_oob_event2str(event_id));
goto event;
}
}
@@ -1610,7 +1636,7 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
sangoma_tdm_txsig_onhook(ftdmchan->sockfd,&tdm_api);
}
ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "Diff since last event = %llums, delivering %s now\n", diff, ftdm_oob_event2str(event_id));
ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "Diff since last event = %"FTDM_TIME_FMT" ms, delivering %s now\n", diff, ftdm_oob_event2str(event_id));
goto event;
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without