Merge branch 'master' into smgmaster

This commit is contained in:
Moises Silva 2010-09-21 14:27:29 -04:00
commit a51a7a269c
14 changed files with 440 additions and 463 deletions

View File

@ -268,13 +268,24 @@ FT_DECLARE(ftdm_status_t) ftdm_conf_node_create(const char *name, ftdm_conf_node
if (parent) {
/* store who my parent is */
newnode->parent = parent;
/* save any siblings */
sibling = parent->child;
/* as a newborn I am first */
parent->child = newnode;
if (sibling) {
/* store a pointer to my next sibling */
newnode->next = sibling;
/* arrange them in FIFO order (newnode should be last) */
if (!parent->child) {
/* we're the first node being added */
parent->child = newnode;
} else {
if (!parent->last) {
/* we're the second node being added */
parent->last = newnode;
parent->child->next = newnode;
newnode->prev = parent->child;
} else {
/* we're the third or Nth node to be added */
sibling = parent->last;
sibling->next = newnode;
parent->last = newnode;
newnode->prev = sibling;
}
}
}

View File

@ -50,6 +50,7 @@
#endif
#include "ftdm_cpu_monitor.h"
#define FORCE_HANGUP_TIMER 3000
#define SPAN_PENDING_CHANS_QUEUE_SIZE 1000
#define SPAN_PENDING_SIGNALS_QUEUE_SIZE 1000
#define FTDM_READ_TRACE_INDEX 0
@ -102,6 +103,7 @@ static struct {
ftdm_mutex_t *mutex;
ftdm_mutex_t *span_mutex;
ftdm_mutex_t *group_mutex;
ftdm_sched_t *timingsched;
uint32_t span_index;
uint32_t group_index;
uint32_t running;
@ -2002,6 +2004,9 @@ static ftdm_status_t call_hangup(ftdm_channel_t *chan, const char *file, const c
/* make user's life easier, and just ignore double hangup requests */
return FTDM_SUCCESS;
}
if (chan->hangup_timer) {
ftdm_sched_cancel_timer(globals.timingsched, chan->hangup_timer);
}
ftdm_channel_set_state(file, func, line, chan, FTDM_CHANNEL_STATE_HANGUP, 1);
} else {
/* the signaling stack did not touch the state,
@ -2283,6 +2288,9 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
close_dtmf_debug(ftdmchan);
#endif
ftdm_channel_clear_vars(ftdmchan);
if (ftdmchan->hangup_timer) {
ftdm_sched_cancel_timer(globals.timingsched, ftdmchan->hangup_timer);
}
ftdmchan->init_state = FTDM_CHANNEL_STATE_DOWN;
ftdmchan->state = FTDM_CHANNEL_STATE_DOWN;
@ -4601,6 +4609,21 @@ FT_DECLARE(ftdm_status_t) ftdm_span_trigger_signals(const ftdm_span_t *span)
return FTDM_SUCCESS;
}
static void execute_safety_hangup(void *data)
{
ftdm_channel_t *fchan = data;
ftdm_channel_lock(fchan);
fchan->hangup_timer = 0;
if (fchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan(fchan, FTDM_LOG_CRIT, "Forcing hangup since the user did not confirmed our hangup after %dms\n", FORCE_HANGUP_TIMER);
call_hangup(fchan, __FILE__, __FUNCTION__, __LINE__);
} else {
ftdm_log_chan(fchan, FTDM_LOG_CRIT, "Not performing safety hangup, channel state is %s\n", ftdm_channel_state2str(fchan->state));
}
ftdm_channel_unlock(fchan);
}
FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
{
if (sigmsg->channel) {
@ -4634,6 +4657,11 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user already requested hangup\n");
goto done;
}
if (sigmsg->channel->state == FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Scheduling safety hangup timer\n");
/* if the user does not move us to hangup in 2 seconds, we will do it ourselves */
ftdm_sched_timer(globals.timingsched, "safety-hangup", FORCE_HANGUP_TIMER, execute_safety_hangup, sigmsg->channel, &sigmsg->channel->hangup_timer);
}
break;
default:
@ -4755,6 +4783,14 @@ FT_DECLARE(ftdm_status_t) ftdm_global_init(void)
ftdm_mutex_create(&globals.span_mutex);
ftdm_mutex_create(&globals.group_mutex);
ftdm_sched_global_init();
if (ftdm_sched_create(&globals.timingsched, "freetdm-master") != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to create master timing schedule context\n");
return FTDM_FAIL;
}
if (ftdm_sched_free_run(globals.timingsched) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to run master timing schedule context\n");
return FTDM_FAIL;
}
globals.running = 1;
return FTDM_SUCCESS;
}
@ -4807,6 +4843,8 @@ FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void)
globals.running = 0;
ftdm_sched_destroy(&globals.timingsched);
ftdm_cpu_monitor_stop();
globals.span_index = 0;

View File

@ -34,6 +34,8 @@
#include "private/ftdm_core.h"
typedef struct ftdm_timer ftdm_timer_t;
static struct {
ftdm_sched_t *freeruns;
ftdm_mutex_t *mutex;
@ -42,6 +44,7 @@ static struct {
struct ftdm_sched {
char name[80];
ftdm_timer_id_t currid;
ftdm_mutex_t *mutex;
ftdm_timer_t *timers;
int freerun;
@ -51,6 +54,7 @@ struct ftdm_sched {
struct ftdm_timer {
char name[80];
ftdm_timer_id_t id;
#ifdef __linux__
struct timeval time;
#endif
@ -191,6 +195,7 @@ FT_DECLARE(ftdm_status_t) ftdm_sched_create(ftdm_sched_t **sched, const char *na
}
ftdm_set_string(newsched->name, name);
newsched->currid = 1;
*sched = newsched;
ftdm_log(FTDM_LOG_DEBUG, "Created schedule %s\n", name);
@ -219,12 +224,13 @@ FT_DECLARE(ftdm_status_t) ftdm_sched_run(ftdm_sched_t *sched)
int rc = -1;
void *data;
struct timeval now;
ftdm_assert_return(sched != NULL, FTDM_EINVAL, "sched is null!\n");
ftdm_mutex_lock(sched->mutex);
tryagain:
ftdm_mutex_lock(sched->mutex);
rc = gettimeofday(&now, NULL);
if (rc == -1) {
ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve time of day\n");
@ -257,11 +263,16 @@ tryagain:
runtimer->prev->next = runtimer->next;
}
runtimer->id = 0;
ftdm_safe_free(runtimer);
/* avoid deadlocks by releasing the sched lock before triggering callbacks */
ftdm_mutex_unlock(sched->mutex);
callback(data);
/* after calling a callback we must start the scanning again since the
* callback may have added or cancelled timers to the linked list */
* callback or some other thread may have added or cancelled timers to
* the linked list */
goto tryagain;
}
}
@ -283,7 +294,7 @@ done:
}
FT_DECLARE(ftdm_status_t) ftdm_sched_timer(ftdm_sched_t *sched, const char *name,
int ms, ftdm_sched_callback_t callback, void *data, ftdm_timer_t **timer)
int ms, ftdm_sched_callback_t callback, void *data, ftdm_timer_id_t *timerid)
{
ftdm_status_t status = FTDM_FAIL;
#ifdef __linux__
@ -296,8 +307,8 @@ FT_DECLARE(ftdm_status_t) ftdm_sched_timer(ftdm_sched_t *sched, const char *name
ftdm_assert_return(callback != NULL, FTDM_EINVAL, "sched callback is null!\n");
ftdm_assert_return(ms > 0, FTDM_EINVAL, "milliseconds must be bigger than 0!\n");
if (timer) {
*timer = NULL;
if (timerid) {
*timerid = 0;
}
rc = gettimeofday(&now, NULL);
@ -312,6 +323,15 @@ FT_DECLARE(ftdm_status_t) ftdm_sched_timer(ftdm_sched_t *sched, const char *name
if (!newtimer) {
goto done;
}
newtimer->id = sched->currid;
sched->currid++;
if (!sched->currid) {
ftdm_log(FTDM_LOG_NOTICE, "Timer id wrap around for sched %s\n", sched->name);
/* we do not want currid to be zero since is an invalid id
* TODO: check that currid does not exists already in the context, it'd be insane
* though, having a timer to live all that time */
sched->currid++;
}
ftdm_set_string(newtimer->name, name);
newtimer->callback = callback;
@ -332,9 +352,10 @@ FT_DECLARE(ftdm_status_t) ftdm_sched_timer(ftdm_sched_t *sched, const char *name
sched->timers = newtimer;
}
if (timer) {
*timer = newtimer;
if (timerid) {
*timerid = newtimer->id;
}
status = FTDM_SUCCESS;
done:
@ -418,53 +439,37 @@ done:
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_sched_cancel_timer(ftdm_sched_t *sched, ftdm_timer_t **intimer)
FT_DECLARE(ftdm_status_t) ftdm_sched_cancel_timer(ftdm_sched_t *sched, ftdm_timer_id_t timerid)
{
ftdm_status_t status = FTDM_FAIL;
ftdm_timer_t *timer;
ftdm_assert_return(sched != NULL, FTDM_EINVAL, "sched is null!\n");
ftdm_assert_return(intimer != NULL, FTDM_EINVAL, "timer is null!\n");
ftdm_assert_return(*intimer != NULL, FTDM_EINVAL, "timer is null!\n");
if (!timerid) {
return FTDM_SUCCESS;
}
ftdm_mutex_lock(sched->mutex);
/* special case where the cancelled timer is the head */
if (*intimer == sched->timers) {
timer = *intimer;
/* the timer next is the new head (even if that means the new head will be NULL)*/
sched->timers = timer->next;
/* if there is a new head, clean its prev member */
if (sched->timers) {
sched->timers->prev = NULL;
}
/* free the old head */
ftdm_safe_free(timer);
status = FTDM_SUCCESS;
*intimer = NULL;
goto done;
}
/* look for the timer and destroy it (we know now that is not head, se we start at the next member after head) */
for (timer = sched->timers->next; timer; timer = timer->next) {
if (timer == *intimer) {
/* look for the timer and destroy it */
for (timer = sched->timers; timer; timer = timer->next) {
if (timer->id == timerid) {
if (timer == sched->timers) {
/* it's the head timer, put a new head */
sched->timers = timer->next;
}
if (timer->prev) {
timer->prev->next = timer->next;
}
if (timer->next) {
timer->next->prev = timer->prev;
}
ftdm_log(FTDM_LOG_DEBUG, "cancelled timer %s\n", timer->name);
ftdm_safe_free(timer);
status = FTDM_SUCCESS;
*intimer = NULL;
break;
}
}
done:
if (status == FTDM_FAIL) {
ftdm_log(FTDM_LOG_ERROR, "Could not find timer %s to cancel it\n", (*intimer)->name);
}
ftdm_mutex_unlock(sched->mutex);

View File

@ -156,7 +156,7 @@ typedef struct sngisdn_chan_data {
uint8_t globalFlg;
sngisdn_glare_data_t glare;
ftdm_timer_t *timers[SNGISDN_NUM_TIMERS];
ftdm_timer_id_t timers[SNGISDN_NUM_TIMERS];
} sngisdn_chan_data_t;
/* Span specific data */

View File

@ -131,14 +131,12 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
}
if (conEvnt->facilityStr.eh.pres) {
if (signal_data->facility == SNGISDN_OPT_TRUE && conEvnt->facilityStr.eh.pres) {
/* Verify whether the Caller Name will come in a subsequent FACILITY message */
uint16_t ret_val;
uint8_t facility_str[255];
char retrieved_str[255];
memcpy(facility_str, (uint8_t*)&conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len);
ret_val = sng_isdn_retrieve_facility_caller_name(facility_str, conEvnt->facilityStr.facilityStr.len, retrieved_str);
ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str);
/*
return values for "sng_isdn_retrieve_facility_information_following":
If there will be no information following, or fails to decode IE, returns -1
@ -151,7 +149,8 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID);
/* Launch timer in case we never get a FACILITY msg */
if (signal_data->facility_timeout) {
ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout,
sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
}
break;
} else if (ret_val == 0) {
@ -702,14 +701,23 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_GET_CALLERID:
/* Update the caller ID Name */
if (facEvnt->facElmt.facStr.pres) {
uint8_t facility_str[255];
memcpy(facility_str, (uint8_t*)&facEvnt->facElmt.facStr.val, facEvnt->facElmt.facStr.len);
char retrieved_str[255];
if (sng_isdn_retrieve_facility_caller_name(facility_str, facEvnt->facElmt.facStr.len, retrieved_str) != FTDM_SUCCESS) {
/* return values for "sng_isdn_retrieve_facility_information_following":
If there will be no information following, or fails to decode IE, returns -1
If there will be no information following, but current FACILITY IE contains a caller name, returns 0
If there will be information following, returns 1
*/
if (sng_isdn_retrieve_facility_caller_name(&facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len, retrieved_str) == 0) {
strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to retrieve Caller Name from Facility IE\n");
}
/* Cancel facility timeout */
ftdm_sched_cancel_timer(signal_data->sched, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
if (signal_data->facility_timeout) {
/* Cancel facility timeout */
ftdm_sched_cancel_timer(signal_data->sched, sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
}
}
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
@ -884,6 +892,22 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
break;
}
break;
case 9: /* Remote switch is in "Incoming call proceeding" state */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_GET_CALLERID:
/* Do nothing */
break;
case FTDM_CHANNEL_STATE_UP:
/* Remote switch missed our CONNECT message, re-send */
ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "delayed_connect", 1, sngisdn_delayed_connect, (void*) sngisdn_info, NULL);
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
}
break;
case 10: /* Remote switch is in active state */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_UP:
@ -899,17 +923,6 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
break;
}
break;
case 9:
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
/* Do nothing */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
}
break;
case 22:
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_UP:

View File

@ -1506,6 +1506,10 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c
sngss7_span_data_t *sngss7_span;
int byte = 0;
int bit = 0;
ftdm_sigmsg_t sigev;
memset (&sigev, 0, sizeof (sigev));
if (range > 31) {
stream->write_function(stream, "Invalid range value %d", range);
@ -1531,6 +1535,14 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c
/* throw the grp maint. block flag */
sngss7_set_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX);
/* bring the sig status down */
sigev.chan_id = ftdmchan->chan_id;
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* if this is the first channel in the range */
if (ftdmchan->physical_chan_id == chan) {
/* attach the cgb information */
@ -1575,6 +1587,10 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
sngss7_span_data_t *sngss7_span;
int byte = 0;
int bit = 0;
ftdm_sigmsg_t sigev;
memset (&sigev, 0, sizeof (sigev));
if (range > 31) {
stream->write_function(stream, "Invalid range value %d", range);
@ -1600,6 +1616,14 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
/* throw the grp maint. block flag */
sngss7_clear_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX);
/* bring the sig status up */
sigev.chan_id = ftdmchan->chan_id;
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* if this is the first channel in the range */
if (ftdmchan->physical_chan_id == chan) {
/* attach the cgb information */

View File

@ -496,6 +496,12 @@ void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
/* initalize the msg variable to NULLs */
memset(&msg[0], '\0', sizeof(&msg));
/* if the event is REMOTE/LOCAL we don't need to print these */
if ((sta->t.usta.alarm.event == LSI_EVENT_REMOTE) ||
(sta->t.usta.alarm.event == LSI_EVENT_LOCAL)) {
return;
}
/* point p to the first spot in msg */
p = &msg[0];
@ -728,6 +734,8 @@ void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
DECODE_LSI_EVENT(sta->t.usta.alarm.event),
DECODE_LSI_CAUSE(sta->t.usta.alarm.cause));
return;
} /* handle_isup_alarm */
/******************************************************************************/

View File

@ -454,9 +454,9 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
/******************************************************************************/
static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
{
ftdm_sigmsg_t sigev;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
int i = 0;
ftdm_sigmsg_t sigev;
memset (&sigev, 0, sizeof (sigev));
@ -788,14 +788,24 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
!(sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX)) &&
!(sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX))) {
/* check if the sig status is down, and bring it up if it isn't */
if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
SS7_DEBUG_CHAN(ftdmchan,"All reset flags cleared %s\n", "");
/* all flags are down so we can bring up the sig status */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
ftdm_span_send_signal (ftdmchan->span, &sigev);
}
/* now check if there is an active block */
if (!(sngss7_test_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) &&
!(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) &&
!(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) &&
!(sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) &&
!(sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) &&
!(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) &&
!(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) {
/* check if the sig status is down, and bring it up if it isn't */
if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
SS7_DEBUG_CHAN(ftdmchan,"All reset flags cleared %s\n", "");
/* all flags are down so we can bring up the sig status */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
ftdm_span_send_signal (ftdmchan->span, &sigev);
} /* if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) */
} /* if !blocked */
} else {
SS7_DEBUG_CHAN(ftdmchan,"Reset flags present (0x%X)\n", sngss7_info->flags);
@ -993,6 +1003,11 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_BLOCK_RX)) {
SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_RX flag %s\n", "");
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a BLA */
ft_to_sngss7_bla (ftdmchan);
@ -1006,6 +1021,11 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* clear the unblock flag */
sngss7_clear_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX);
/* bring the sig status up */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a uba */
ft_to_sngss7_uba (ftdmchan);
@ -1017,6 +1037,11 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_BLOCK_TX)) {
SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_TX flag %s\n", "");
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a blo */
ft_to_sngss7_blo (ftdmchan);
@ -1030,6 +1055,11 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* clear the unblock flag */
sngss7_clear_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX);
/* bring the sig status up */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a ubl */
ft_to_sngss7_ubl (ftdmchan);
@ -1403,6 +1433,9 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_ss7_span_config)
static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init)
{
/*this function is called by the FT-core to load the signaling module */
uint32_t major = 0;
uint32_t minor = 0;
uint32_t build = 0;
ftdm_log (FTDM_LOG_INFO, "Loading ftmod_sangoma_ss7...\n");
@ -1452,6 +1485,10 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init)
/* initalize sng_ss7 library */
sng_isup_init (&sng_event);
/* print the version of the library being used */
sng_isup_version(&major, &minor, &build);
SS7_INFO("Loaded LibSng-SS7 %d.%d.%d\n", major, minor, build);
/* crash on assert fail */
ftdm_global_set_crash_policy (FTDM_CRASH_ON_ASSERT);

View File

@ -199,7 +199,8 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
&iam,
0);
SS7_INFO_CHAN(ftdmchan,"Tx IAM clg = \"%s\", cld = \"%s\"\n",
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM clg = \"%s\", cld = \"%s\"\n",
sngss7_info->circuit->cic,
ftdmchan->caller_data.cid_num.digits,
ftdmchan->caller_data.dnis.digits);
@ -250,7 +251,7 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
&acm,
ADDRCMPLT);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx ACM\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ACM\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -274,7 +275,7 @@ void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan)
&anm,
5);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx ANM\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ANM\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -307,7 +308,9 @@ void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan)
sngss7_info->circuit->id,
&rel);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx REL\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx REL cause=%d \n",
sngss7_info->circuit->cic,
ftdmchan->caller_data.hangup_cause );
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -330,7 +333,7 @@ void ft_to_sngss7_rlc (ftdm_channel_t * ftdmchan)
sngss7_info->circuit->id,
&rlc);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx RLC\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RLC\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -351,7 +354,7 @@ void ft_to_sngss7_rsc (ftdm_channel_t * ftdmchan)
SIT_STA_CIRRESREQ,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx RSC\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -372,7 +375,7 @@ void ft_to_sngss7_rsca (ftdm_channel_t * ftdmchan)
SIT_STA_CIRRESRSP,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx RSC-RLC\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC-RLC\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -393,7 +396,7 @@ void ft_to_sngss7_blo (ftdm_channel_t * ftdmchan)
SIT_STA_CIRBLOREQ,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx BLO\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLO\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -414,7 +417,7 @@ void ft_to_sngss7_bla (ftdm_channel_t * ftdmchan)
SIT_STA_CIRBLORSP,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx BLA\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLA\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -436,7 +439,7 @@ ft_to_sngss7_ubl (ftdm_channel_t * ftdmchan)
SIT_STA_CIRUBLREQ,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx UBL\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBL\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -457,7 +460,7 @@ void ft_to_sngss7_uba (ftdm_channel_t * ftdmchan)
SIT_STA_CIRUBLRSP,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx UBA\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBA\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -478,7 +481,7 @@ void ft_to_sngss7_lpa (ftdm_channel_t * ftdmchan)
SIT_STA_LOOPBACKACK,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx LPA\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx LPA\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -519,7 +522,8 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
SIT_STA_GRSRSP,
&gra);
SS7_INFO_CHAN(ftdmchan, "Tx GRA (%d:%d)\n",
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx GRA (%d:%d)\n",
sngss7_info->circuit->cic,
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->rx_grs.range));
@ -551,7 +555,8 @@ void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan)
SIT_STA_GRSREQ,
&grs);
SS7_INFO_CHAN(ftdmchan, "Tx GRS (%d:%d)\n",
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx GRS (%d:%d)\n",
sngss7_info->circuit->cic,
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->tx_grs.range));
@ -596,7 +601,8 @@ void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan)
SIT_STA_CGBRSP,
&cgba);
SS7_INFO_CHAN(ftdmchan, "Tx CGBA (%d:%d)\n",
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx CGBA (%d:%d)\n",
sngss7_info->circuit->cic,
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->rx_cgb.range));
@ -644,7 +650,8 @@ void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan)
SIT_STA_CGURSP,
&cgua);
SS7_INFO_CHAN(ftdmchan, "Tx CGUA (%d:%d)\n",
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx CGUA (%d:%d)\n",
sngss7_info->circuit->cic,
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->rx_cgu.range));
@ -693,7 +700,8 @@ void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan)
SIT_STA_CGBREQ,
&cgb);
SS7_INFO_CHAN(ftdmchan, "Tx CGB (%d:%d)\n",
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx CGB (%d:%d)\n",
sngss7_info->circuit->cic,
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->tx_cgb.range));
@ -742,7 +750,8 @@ void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan)
SIT_STA_CGUREQ,
&cgu);
SS7_INFO_CHAN(ftdmchan, "Tx CGU (%d:%d)\n",
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx CGU (%d:%d)\n",
sngss7_info->circuit->cic,
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->tx_cgu.range));

View File

@ -464,7 +464,7 @@ ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan)
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
SS7_ASSERT;
continue;
}
/* lock the channel */
@ -476,61 +476,61 @@ ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan)
if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) {
/* this channel is still resetting...do nothing */
goto GRS_UNLOCK_ALL;
} /* if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */
} else {
/* state change pending */
goto GRS_UNLOCK_ALL;
}
} /* for ( i = circuit; i < (circuit + range + 1); i++) */
} /* if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */
} else {
/* state change pending */
goto GRS_UNLOCK_ALL;
}
} /* for ( i = circuit; i < (circuit + range + 1); i++) */
SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n",
sngss7_span->rx_grs.circuit,
sngss7_span->rx_grs.range);
SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n",
sngss7_span->rx_grs.circuit,
sngss7_span->rx_grs.range);
/* check all the circuits in the range to see if they are done resetting */
for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* check all the circuits in the range to see if they are done resetting */
for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i);
SS7_ASSERT;
}
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i);
SS7_ASSERT;
}
/* throw the GRP reset flag complete flag */
sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
/* throw the GRP reset flag complete flag */
sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
/* move the channel to the down state */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
/* move the channel to the down state */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
/* update the status map if the ckt is in blocked state */
if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) ||
(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) ||
(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
sngss7_span->rx_grs.status[byte] = (sngss7_span->rx_grs.status[byte] | (1 << bit));
} /* if blocked */
/* update the bit and byte counter*/
bit ++;
if (bit == 8) {
byte++;
bit = 0;
}
} /* for ( i = circuit; i < (circuit + range + 1); i++) */
/* update the status map if the ckt is in blocked state */
if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) ||
(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) ||
(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
sngss7_span->rx_grs.status[byte] = (sngss7_span->rx_grs.status[byte] | (1 << bit));
} /* if blocked */
/* update the bit and byte counter*/
bit ++;
if (bit == 8) {
byte++;
bit = 0;
}
} /* for ( i = circuit; i < (circuit + range + 1); i++) */
GRS_UNLOCK_ALL:
for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
SS7_ASSERT;
}
/* unlock the channel */
ftdm_mutex_unlock(ftdmchan->mutex);
for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
continue;
}
/* unlock the channel */
ftdm_mutex_unlock(ftdmchan->mutex);
}
return FTDM_SUCCESS;
}

View File

@ -425,6 +425,7 @@ struct ftdm_channel {
float txgain;
int availability_rate;
void *user_private;
ftdm_timer_id_t hangup_timer;
#ifdef FTDM_DEBUG_DTMF
ftdm_dtmf_debug_t dtmfdbg;
#endif

View File

@ -44,8 +44,8 @@ extern "C" {
#define FTDM_MICROSECONDS_PER_SECOND 1000000
typedef struct ftdm_sched ftdm_sched_t;
typedef struct ftdm_timer ftdm_timer_t;
typedef void (*ftdm_sched_callback_t)(void *data);
typedef uint64_t ftdm_timer_id_t;
/*! \brief Create a new scheduling context */
FT_DECLARE(ftdm_status_t) ftdm_sched_create(ftdm_sched_t **sched, const char *name);
@ -62,18 +62,22 @@ FT_DECLARE(ftdm_status_t) ftdm_sched_free_run(ftdm_sched_t *sched);
* \param name Timer name, typically unique but is not required to be unique, any null terminated string is fine (required)
* \param callback The callback to call upon timer expiration (required)
* \param data Optional data to pass to the callback
* \param timer The timer that was created, it can be NULL if you dont care,
* but you need this if you want to be able to cancel the timer with ftdm_sched_cancel_timer
* \param timer Timer id pointer to store the id of the newly created timer. It can be null
* if you do not need to know the id, but you need this if you want to be able
* to cancel the timer with ftdm_sched_cancel_timer
*/
FT_DECLARE(ftdm_status_t) ftdm_sched_timer(ftdm_sched_t *sched, const char *name,
int ms, ftdm_sched_callback_t callback, void *data, ftdm_timer_t **timer);
int ms, ftdm_sched_callback_t callback, void *data, ftdm_timer_id_t *timer);
/*!
* \brief Cancel the timer
* Note that there is a race between cancelling and triggering a timer.
* By the time you call this function the timer may be about to be triggered.
* This is specially true with timers in free run schedule.
* \param sched The scheduling context (required)
* \param timer The timer to cancel (required)
*/
FT_DECLARE(ftdm_status_t) ftdm_sched_cancel_timer(ftdm_sched_t *sched, ftdm_timer_t **timer);
FT_DECLARE(ftdm_status_t) ftdm_sched_cancel_timer(ftdm_sched_t *sched, ftdm_timer_id_t timer);
/*! \brief Destroy the context and all of the scheduled timers in it */
FT_DECLARE(ftdm_status_t) ftdm_sched_destroy(ftdm_sched_t **sched);

View File

@ -322,9 +322,15 @@ struct ftdm_conf_node {
/* first node child */
struct ftdm_conf_node *child;
/* last node child */
struct ftdm_conf_node *last;
/* next node sibling */
struct ftdm_conf_node *next;
/* prev node sibling */
struct ftdm_conf_node *prev;
/* my parent if any */
struct ftdm_conf_node *parent;
};