mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-11-11 20:17:05 +00:00
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:
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
|
||||
|
||||
Executable
+1329
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
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Regular → Executable
+45
-19
@@ -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,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
|
||||
|
||||
Reference in new issue
Block a user