freetdm: Initial attempt to bridge natively SS7 signaling between 2 channels
This commit is contained in:
parent
b4e8d5b608
commit
23a328389b
|
@ -53,8 +53,6 @@ struct tm *localtime_r(const time_t *clock, struct tm *result);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FORCE_HANGUP_TIMER 30000
|
#define FORCE_HANGUP_TIMER 30000
|
||||||
#define SPAN_PENDING_CHANS_QUEUE_SIZE 1000
|
|
||||||
#define SPAN_PENDING_SIGNALS_QUEUE_SIZE 1000
|
|
||||||
#define FTDM_READ_TRACE_INDEX 0
|
#define FTDM_READ_TRACE_INDEX 0
|
||||||
#define FTDM_WRITE_TRACE_INDEX 1
|
#define FTDM_WRITE_TRACE_INDEX 1
|
||||||
#define MAX_CALLIDS 6000
|
#define MAX_CALLIDS 6000
|
||||||
|
@ -2201,6 +2199,12 @@ static ftdm_status_t _ftdm_channel_call_hangup_nl(const char *file, const char *
|
||||||
{
|
{
|
||||||
ftdm_status_t status = FTDM_SUCCESS;
|
ftdm_status_t status = FTDM_SUCCESS;
|
||||||
|
|
||||||
|
if (ftdm_test_flag(chan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) {
|
||||||
|
ftdm_log_chan_ex(chan, file, func, line, FTDM_LOG_LEVEL_DEBUG,
|
||||||
|
"Ignoring hangup in channel in state %s (native bridge enabled)\n", ftdm_channel_state2str(chan->state));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (chan->state != FTDM_CHANNEL_STATE_DOWN) {
|
if (chan->state != FTDM_CHANNEL_STATE_DOWN) {
|
||||||
if (chan->state == FTDM_CHANNEL_STATE_HANGUP) {
|
if (chan->state == FTDM_CHANNEL_STATE_HANGUP) {
|
||||||
/* make user's life easier, and just ignore double hangup requests */
|
/* make user's life easier, and just ignore double hangup requests */
|
||||||
|
@ -2227,6 +2231,8 @@ static ftdm_status_t _ftdm_channel_call_hangup_nl(const char *file, const char *
|
||||||
ftdm_channel_close(&chan);
|
ftdm_channel_close(&chan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2322,6 +2328,15 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
|
||||||
|
|
||||||
ftdm_channel_lock(ftdmchan);
|
ftdm_channel_lock(ftdmchan);
|
||||||
|
|
||||||
|
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) {
|
||||||
|
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_DEBUG,
|
||||||
|
"Ignoring indication %s in channel in state %s (native bridge enabled)\n",
|
||||||
|
ftdm_channel_indication2str(indication),
|
||||||
|
ftdm_channel_state2str(ftdmchan->state));
|
||||||
|
status = FTDM_SUCCESS;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IND_ACK_PENDING)) {
|
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IND_ACK_PENDING)) {
|
||||||
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "Cannot indicate %s in channel with indication %s still pending in state %s\n",
|
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "Cannot indicate %s in channel with indication %s still pending in state %s\n",
|
||||||
ftdm_channel_indication2str(indication),
|
ftdm_channel_indication2str(indication),
|
||||||
|
@ -2422,10 +2437,50 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func
|
||||||
return FTDM_SUCCESS;
|
return FTDM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FT_DECLARE(ftdm_status_t) ftdm_get_channel_from_string(const char *string_id, ftdm_span_t **out_span, ftdm_channel_t **out_channel)
|
||||||
|
{
|
||||||
|
ftdm_status_t status = FTDM_SUCCESS;
|
||||||
|
int rc = 0;
|
||||||
|
ftdm_span_t *span = NULL;
|
||||||
|
ftdm_channel_t *ftdmchan = NULL;
|
||||||
|
unsigned span_id = 0;
|
||||||
|
unsigned chan_id = 0;
|
||||||
|
|
||||||
|
*out_span = NULL;
|
||||||
|
*out_channel = NULL;
|
||||||
|
|
||||||
|
rc = sscanf(string_id, "%u:%u", &span_id, &chan_id);
|
||||||
|
if (rc != 2) {
|
||||||
|
ftdm_log(FTDM_LOG_ERROR, "Failed to parse channel id string '%s'\n", string_id);
|
||||||
|
status = FTDM_EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = ftdm_span_find(span_id, &span);
|
||||||
|
if (status != FTDM_SUCCESS || !span) {
|
||||||
|
ftdm_log(FTDM_LOG_ERROR, "Failed to find span for channel id string '%s'\n", string_id);
|
||||||
|
status = FTDM_EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chan_id > (FTDM_MAX_CHANNELS_SPAN+1) || !(ftdmchan = span->channels[chan_id])) {
|
||||||
|
ftdm_log(FTDM_LOG_ERROR, "Invalid channel id string '%s'\n", string_id);
|
||||||
|
status = FTDM_EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = FTDM_SUCCESS;
|
||||||
|
*out_span = span;
|
||||||
|
*out_channel = ftdmchan;
|
||||||
|
done:
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
/* this function MUST be called with the channel lock held with lock recursivity of 1 exactly,
|
/* this function MUST be called with the channel lock held with lock recursivity of 1 exactly,
|
||||||
* and the caller must be aware we might unlock the channel for a brief period of time and then lock it again */
|
* and the caller must be aware we might unlock the channel for a brief period of time and then lock it again */
|
||||||
static ftdm_status_t _ftdm_channel_call_place_nl(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg)
|
static ftdm_status_t _ftdm_channel_call_place_nl(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg)
|
||||||
{
|
{
|
||||||
|
const char *var = NULL;
|
||||||
ftdm_status_t status = FTDM_FAIL;
|
ftdm_status_t status = FTDM_FAIL;
|
||||||
|
|
||||||
ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel");
|
ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel");
|
||||||
|
@ -2461,6 +2516,17 @@ static ftdm_status_t _ftdm_channel_call_place_nl(const char *file, const char *f
|
||||||
|
|
||||||
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED);
|
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED);
|
||||||
ftdm_call_set_call_id(ftdmchan, &ftdmchan->caller_data);
|
ftdm_call_set_call_id(ftdmchan, &ftdmchan->caller_data);
|
||||||
|
var = ftdm_usrmsg_get_var(usrmsg, "sigbridge_peer");
|
||||||
|
if (var) {
|
||||||
|
ftdm_span_t *peer_span = NULL;
|
||||||
|
ftdm_channel_t *peer_chan = NULL;
|
||||||
|
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "enabling native signaling bridge!\n");
|
||||||
|
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE);
|
||||||
|
ftdm_get_channel_from_string(var, &peer_span, &peer_chan);
|
||||||
|
if (peer_chan) {
|
||||||
|
ftdm_set_flag(peer_chan, FTDM_CHANNEL_NATIVE_SIGBRIDGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* if the signaling stack left the channel in state down on success, is expecting us to move to DIALING */
|
/* if the signaling stack left the channel in state down on success, is expecting us to move to DIALING */
|
||||||
if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) {
|
if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) {
|
||||||
|
@ -2662,6 +2728,7 @@ static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan)
|
||||||
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_ANSWERED);
|
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_ANSWERED);
|
||||||
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_USER_HANGUP);
|
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_USER_HANGUP);
|
||||||
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DIGITAL_MEDIA);
|
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DIGITAL_MEDIA);
|
||||||
|
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE);
|
||||||
ftdm_mutex_lock(ftdmchan->pre_buffer_mutex);
|
ftdm_mutex_lock(ftdmchan->pre_buffer_mutex);
|
||||||
ftdm_buffer_destroy(&ftdmchan->pre_buffer);
|
ftdm_buffer_destroy(&ftdmchan->pre_buffer);
|
||||||
ftdmchan->pre_buffer_size = 0;
|
ftdmchan->pre_buffer_size = 0;
|
||||||
|
|
|
@ -55,6 +55,7 @@ ftdm_sngss7_data_t g_ftdm_sngss7_data;
|
||||||
/* PROTOTYPES *****************************************************************/
|
/* PROTOTYPES *****************************************************************/
|
||||||
static void *ftdm_sangoma_ss7_run (ftdm_thread_t * me, void *obj);
|
static void *ftdm_sangoma_ss7_run (ftdm_thread_t * me, void *obj);
|
||||||
static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_event);
|
static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_event);
|
||||||
|
static void ftdm_sangoma_ss7_process_peer_stack_event (ftdm_channel_t *ftdmchan, sngss7_event_data_t *sngss7_event);
|
||||||
|
|
||||||
static ftdm_status_t ftdm_sangoma_ss7_stop (ftdm_span_t * span);
|
static ftdm_status_t ftdm_sangoma_ss7_stop (ftdm_span_t * span);
|
||||||
static ftdm_status_t ftdm_sangoma_ss7_start (ftdm_span_t * span);
|
static ftdm_status_t ftdm_sangoma_ss7_start (ftdm_span_t * span);
|
||||||
|
@ -338,9 +339,10 @@ static void handle_hw_alarm(ftdm_event_t *e)
|
||||||
/* MONITIOR THREADS ***********************************************************/
|
/* MONITIOR THREADS ***********************************************************/
|
||||||
static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
|
static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
|
||||||
{
|
{
|
||||||
ftdm_interrupt_t *ftdm_sangoma_ss7_int[2];
|
ftdm_interrupt_t *ftdm_sangoma_ss7_int[3];
|
||||||
ftdm_span_t *ftdmspan = (ftdm_span_t *) obj;
|
ftdm_span_t *ftdmspan = (ftdm_span_t *) obj;
|
||||||
ftdm_channel_t *ftdmchan = NULL;
|
ftdm_channel_t *ftdmchan = NULL;
|
||||||
|
ftdm_channel_t *peerchan = NULL;
|
||||||
ftdm_event_t *event = NULL;
|
ftdm_event_t *event = NULL;
|
||||||
sngss7_event_data_t *sngss7_event = NULL;
|
sngss7_event_data_t *sngss7_event = NULL;
|
||||||
sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
|
sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
|
||||||
|
@ -365,6 +367,12 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
|
||||||
goto ftdm_sangoma_ss7_run_exit;
|
goto ftdm_sangoma_ss7_run_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get an interrupt queue for this span for peer channel events */
|
||||||
|
if (ftdm_queue_get_interrupt (sngss7_span->peer_chans, &ftdm_sangoma_ss7_int[2]) != FTDM_SUCCESS) {
|
||||||
|
SS7_CRITICAL ("Failed to get a ftdm_interrupt for span = %d for peer channel events queue!\n", ftdmspan->span_id);
|
||||||
|
goto ftdm_sangoma_ss7_run_exit;
|
||||||
|
}
|
||||||
|
|
||||||
while (ftdm_running () && !(ftdm_test_flag (ftdmspan, FTDM_SPAN_STOP_THREAD))) {
|
while (ftdm_running () && !(ftdm_test_flag (ftdmspan, FTDM_SPAN_STOP_THREAD))) {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
if (b_alarm_test) {
|
if (b_alarm_test) {
|
||||||
|
@ -395,7 +403,7 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check the channel state queue for an event*/
|
/* check the channel state queue for an event*/
|
||||||
switch ((ftdm_interrupt_multiple_wait(ftdm_sangoma_ss7_int, 2, 100))) {
|
switch ((ftdm_interrupt_multiple_wait(ftdm_sangoma_ss7_int, ftdm_array_len(ftdm_sangoma_ss7_int), 100))) {
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
case FTDM_SUCCESS: /* process all pending state changes */
|
case FTDM_SUCCESS: /* process all pending state changes */
|
||||||
|
|
||||||
|
@ -412,6 +420,31 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
|
||||||
ftdm_mutex_unlock (ftdmchan->mutex);
|
ftdm_mutex_unlock (ftdmchan->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* clean out all peer pending channel events */
|
||||||
|
while ((peerchan = ftdm_queue_dequeue (sngss7_span->peer_chans))) {
|
||||||
|
/* note that the channels being dequeued here may not belong to this span
|
||||||
|
they may belong to just about any other span that one of our channels
|
||||||
|
happens to be bridged to */
|
||||||
|
sngss7_chan_data_t *peer_info = peerchan->call_data;
|
||||||
|
sngss7_chan_data_t *chan_info = peer_info->peer_data;
|
||||||
|
ftdmchan = chan_info->ftdmchan;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if there is any state changes at all, those will be done in the opposite channel
|
||||||
|
to peerchan (where the original event was received), therefore we must lock ftdmchan,
|
||||||
|
but do not need to lock peerchan as we only read its event queue, which is already
|
||||||
|
locked when dequeueing */
|
||||||
|
ftdm_channel_lock(ftdmchan);
|
||||||
|
|
||||||
|
/* clean out all pending stack events in the peer channel */
|
||||||
|
while ((sngss7_event = ftdm_queue_dequeue(peer_info->event_queue))) {
|
||||||
|
ftdm_sangoma_ss7_process_peer_stack_event(ftdmchan, sngss7_event);
|
||||||
|
ftdm_safe_free(sngss7_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
ftdm_channel_lock(ftdmchan);
|
||||||
|
}
|
||||||
|
|
||||||
/* clean out all pending stack events */
|
/* clean out all pending stack events */
|
||||||
while ((sngss7_event = ftdm_queue_dequeue(sngss7_span->event_queue))) {
|
while ((sngss7_event = ftdm_queue_dequeue(sngss7_span->event_queue))) {
|
||||||
ftdm_sangoma_ss7_process_stack_event(sngss7_event);
|
ftdm_sangoma_ss7_process_stack_event(sngss7_event);
|
||||||
|
@ -522,24 +555,60 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
|
||||||
/* now that we have the right channel ... put a lock on it so no-one else can use it */
|
/* now that we have the right channel ... put a lock on it so no-one else can use it */
|
||||||
ftdm_channel_lock(ftdmchan);
|
ftdm_channel_lock(ftdmchan);
|
||||||
|
|
||||||
if (sngss7_info->event_queue) {
|
/* while there's a state change present on this channel process it */
|
||||||
if (sngss7_event->event_id == SNGSS7_CON_IND_EVENT) {
|
ftdm_channel_advance_states(ftdmchan);
|
||||||
/* this is the first event in a call, flush the event queue */
|
|
||||||
while ((event_clone = ftdm_queue_dequeue(sngss7_info->event_queue))) {
|
if (sngss7_event->event_id == SNGSS7_CON_IND_EVENT) {
|
||||||
SS7_WARN("[CIC:%d]Discarding clone event from past call!\n", sngss7_info->circuit->cic);
|
/* this is the first event in a call, flush the event queue */
|
||||||
ftdm_safe_free(event_clone);
|
while ((event_clone = ftdm_queue_dequeue(sngss7_info->event_queue))) {
|
||||||
}
|
SS7_WARN("[CIC:%d]Discarding clone event from past call!\n", sngss7_info->circuit->cic);
|
||||||
}
|
ftdm_safe_free(event_clone);
|
||||||
/* clone the event and save it for later usage */
|
|
||||||
event_clone = ftdm_calloc(1, sizeof(*sngss7_event));
|
|
||||||
if (event_clone) {
|
|
||||||
memcpy(event_clone, sngss7_event, sizeof(*sngss7_event));
|
|
||||||
ftdm_queue_enqueue(sngss7_info->event_queue, event_clone);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* while there's a state change present on this channel process it */
|
/* clone the event and save it for later usage */
|
||||||
ftdm_channel_advance_states(ftdmchan);
|
event_clone = ftdm_calloc(1, sizeof(*sngss7_event));
|
||||||
|
if (event_clone) {
|
||||||
|
memcpy(event_clone, sngss7_event, sizeof(*sngss7_event));
|
||||||
|
ftdm_queue_enqueue(sngss7_info->event_queue, event_clone);
|
||||||
|
if (sngss7_info->peer_data) {
|
||||||
|
sngss7_span_data_t *sngss7_peer_span = (sngss7_span_data_t *)sngss7_info->peer_data->ftdmchan->span->signal_data;
|
||||||
|
/* we already have a peer attached, wake him up */
|
||||||
|
ftdm_queue_enqueue(sngss7_peer_span->peer_chans, sngss7_info->ftdmchan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we could test for sngss7_info->peer_data too, bit this flag is set earlier, the earlier we know the better */
|
||||||
|
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) {
|
||||||
|
/* most messages are simply relayed in sig bridge mode, except for hangup which requires state changing */
|
||||||
|
switch (sngss7_event->event_id) {
|
||||||
|
case SNGSS7_REL_IND_EVENT:
|
||||||
|
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||||
|
break;
|
||||||
|
case SNGSS7_REL_CFM_EVENT:
|
||||||
|
{
|
||||||
|
ftdm_channel_t *peer_chan = sngss7_info->peer_data->ftdmchan;
|
||||||
|
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
|
||||||
|
if (peer_chan) {
|
||||||
|
/* we need to unlock our chan or we risk deadlock */
|
||||||
|
ftdm_channel_advance_states(ftdmchan);
|
||||||
|
ftdm_channel_unlock(ftdmchan);
|
||||||
|
|
||||||
|
ftdm_channel_lock(peer_chan);
|
||||||
|
if (peer_chan->state != FTDM_CHANNEL_STATE_DOWN) {
|
||||||
|
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
|
||||||
|
}
|
||||||
|
ftdm_channel_unlock(peer_chan);
|
||||||
|
|
||||||
|
ftdm_channel_lock(ftdmchan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/* figure out the type of event and send it to the right handler */
|
/* figure out the type of event and send it to the right handler */
|
||||||
switch (sngss7_event->event_id) {
|
switch (sngss7_event->event_id) {
|
||||||
|
@ -602,6 +671,7 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
/* while there's a state change present on this channel process it */
|
/* while there's a state change present on this channel process it */
|
||||||
ftdm_channel_advance_states(ftdmchan);
|
ftdm_channel_advance_states(ftdmchan);
|
||||||
|
|
||||||
|
@ -610,8 +680,290 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FTDM_ENUM_NAMES(SNG_EVENT_TYPE_NAMES, SNG_EVENT_TYPE_STRINGS)
|
||||||
|
FTDM_STR2ENUM(ftdm_str2sngss7_event, ftdm_sngss7_event2str, sng_event_type_t, SNG_EVENT_TYPE_NAMES, SNGSS7_INVALID_EVENT)
|
||||||
|
static void ftdm_sangoma_ss7_process_peer_stack_event (ftdm_channel_t *ftdmchan, sngss7_event_data_t *sngss7_event)
|
||||||
|
{
|
||||||
|
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
|
||||||
|
|
||||||
|
if (ftdmchan->state < FTDM_CHANNEL_STATE_UP) {
|
||||||
|
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
|
||||||
|
ftdm_channel_advance_states(ftdmchan);
|
||||||
|
}
|
||||||
|
|
||||||
|
SS7_ERROR_CHAN(ftdmchan,"[CIC:%d]Relaying message %s from bridged peer\n",
|
||||||
|
sngss7_info->circuit->cic, ftdm_sngss7_event2str(sngss7_event->event_id));
|
||||||
|
|
||||||
|
switch (sngss7_event->event_id) {
|
||||||
|
|
||||||
|
case (SNGSS7_CON_IND_EVENT):
|
||||||
|
SS7_ERROR_CHAN(ftdmchan,"[CIC:%d]Rx IAM (bridged)??\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (SNGSS7_CON_CFM_EVENT):
|
||||||
|
/* send the ANM request to LibSngSS7 */
|
||||||
|
sng_cc_con_response(1,
|
||||||
|
sngss7_info->suInstId,
|
||||||
|
sngss7_info->spInstId,
|
||||||
|
sngss7_info->circuit->id,
|
||||||
|
&sngss7_event->event.siConEvnt,
|
||||||
|
5);
|
||||||
|
|
||||||
|
SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Tx peer ANM\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (SNGSS7_CON_STA_EVENT):
|
||||||
|
switch (sngss7_event->evntType) {
|
||||||
|
/**************************************************************************/
|
||||||
|
case (ADDRCMPLT):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer ACM\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (MODIFY):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer MODIFY\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (MODCMPLT):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer MODIFY-COMPLETE\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (MODREJ):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer MODIFY-REJECT\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (PROGRESS):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CPG\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (FRWDTRSFR):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer FOT\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (INFORMATION):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer INF\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (INFORMATREQ):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer INR\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (SUBSADDR):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer SAM\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (EXIT):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer EXIT\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (NETRESMGT):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer NRM\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (IDENTREQ):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer IDR\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (IDENTRSP):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer IRS\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (MALCLLPRNT):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer MALICIOUS CALL\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (CHARGE):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CRG\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (TRFFCHGE):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CRG-TARIFF\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (CHARGEACK):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CRG-ACK\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (CALLOFFMSG):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CALL-OFFER\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (LOOPPRVNT):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer LOP\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (TECT_TIMEOUT):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer ECT-Timeout\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (RINGSEND):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer RINGING-SEND\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (CALLCLEAR):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CALL-LINE Clear\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (PRERELEASE):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer PRI\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (APPTRANSPORT):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer APM\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (OPERATOR):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer OPERATOR\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (METPULSE):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer METERING-PULSE\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (CLGPTCLR):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CALLING_PARTY_CLEAR\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (SUBDIRNUM):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer SUB-DIR\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
#ifdef SANGOMA_SPIROU
|
||||||
|
case (CHARGE_ACK):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer TXA\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
case (CHARGE_UNIT):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer ITX\n", sngss7_info->circuit->cic);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
/**************************************************************************/
|
||||||
|
default:
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer Unknown Msg %d\n", sngss7_info->circuit->cic, sngss7_event->evntType);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
}
|
||||||
|
sng_cc_con_status (1,
|
||||||
|
sngss7_info->suInstId,
|
||||||
|
sngss7_info->spInstId,
|
||||||
|
sngss7_info->circuit->id,
|
||||||
|
&sngss7_event->event.siCnStEvnt,
|
||||||
|
sngss7_event->evntType);
|
||||||
|
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (SNGSS7_REL_IND_EVENT):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer REL cause=%d\n", sngss7_info->circuit->cic, sngss7_event->event.siRelEvnt.causeDgn.causeVal.val);
|
||||||
|
|
||||||
|
//handle_rel_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siRelEvnt);
|
||||||
|
sng_cc_rel_request (1,
|
||||||
|
sngss7_info->suInstId,
|
||||||
|
sngss7_info->spInstId,
|
||||||
|
sngss7_info->circuit->id,
|
||||||
|
&sngss7_event->event.siRelEvnt);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
case (SNGSS7_REL_CFM_EVENT):
|
||||||
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer RLC\n", sngss7_info->circuit->cic);
|
||||||
|
sng_cc_rel_response (1,
|
||||||
|
sngss7_info->suInstId,
|
||||||
|
sngss7_info->spInstId,
|
||||||
|
sngss7_info->circuit->id,
|
||||||
|
&sngss7_event->event.siRelEvnt);
|
||||||
|
//handle_rel_cfm(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siRelEvnt);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
case (SNGSS7_DAT_IND_EVENT):
|
||||||
|
//handle_dat_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siInfoEvnt);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (SNGSS7_FAC_IND_EVENT):
|
||||||
|
//handle_fac_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->evntType, &sngss7_event->event.siFacEvnt);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (SNGSS7_FAC_CFM_EVENT):
|
||||||
|
//handle_fac_cfm(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->evntType, &sngss7_event->event.siFacEvnt);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (SNGSS7_UMSG_IND_EVENT):
|
||||||
|
//handle_umsg_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (SNGSS7_STA_IND_EVENT):
|
||||||
|
//handle_sta_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->globalFlg, sngss7_event->evntType, &sngss7_event->event.siStaEvnt);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (SNGSS7_SUSP_IND_EVENT):
|
||||||
|
//handle_susp_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siSuspEvnt);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (SNGSS7_RESM_IND_EVENT):
|
||||||
|
//handle_resm_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siResmEvnt);
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
case (SNGSS7_SSP_STA_CFM_EVENT):
|
||||||
|
SS7_ERROR("dazed and confused ... hu?!\n");
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
default:
|
||||||
|
SS7_ERROR("Unknown Event Id!\n");
|
||||||
|
break;
|
||||||
|
/**************************************************************************/
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static ftdm_status_t ftdm_sangoma_ss7_native_bridge_state_change(ftdm_channel_t *ftdmchan);
|
||||||
|
static ftdm_status_t ftdm_sangoma_ss7_native_bridge_state_change(ftdm_channel_t *ftdmchan)
|
||||||
|
{
|
||||||
|
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
|
||||||
|
|
||||||
|
ftdm_channel_complete_state(ftdmchan);
|
||||||
|
|
||||||
|
switch (ftdmchan->state) {
|
||||||
|
|
||||||
|
case FTDM_CHANNEL_STATE_DOWN:
|
||||||
|
{
|
||||||
|
/* both peers come here after the channel processing the RLC moves the pair to DOWN */
|
||||||
|
ftdm_channel_t *close_chan = ftdmchan;
|
||||||
|
|
||||||
|
/* detach native bridging if needed (only the outbound leg is responsible for that to avoid races or messy locks) */
|
||||||
|
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
|
||||||
|
sngss7_chan_data_t *peer_info = sngss7_info->peer_data;
|
||||||
|
sngss7_info->peer_data = NULL;
|
||||||
|
if (peer_info) {
|
||||||
|
peer_info->peer_data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close the channel */
|
||||||
|
ftdm_channel_close (&close_chan);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FTDM_CHANNEL_STATE_UP:
|
||||||
|
{
|
||||||
|
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
|
||||||
|
sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_UP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FTDM_CHANNEL_STATE_TERMINATING:
|
||||||
|
{
|
||||||
|
/* when receiving REL we move to TERMINATING and notify the user that the bridge is ending */
|
||||||
|
sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_STOP);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FTDM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
|
ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t *ftdmchan)
|
||||||
{
|
{
|
||||||
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
|
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
|
||||||
sng_isup_inf_t *isup_intf = NULL;
|
sng_isup_inf_t *isup_intf = NULL;
|
||||||
|
@ -623,6 +975,9 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
|
||||||
sngss7_info->ckt_flags,
|
sngss7_info->ckt_flags,
|
||||||
sngss7_info->blk_flags);
|
sngss7_info->blk_flags);
|
||||||
|
|
||||||
|
if (sngss7_info->peer_data) {
|
||||||
|
return ftdm_sangoma_ss7_native_bridge_state_change(ftdmchan);
|
||||||
|
}
|
||||||
|
|
||||||
/*check what state we are supposed to be in */
|
/*check what state we are supposed to be in */
|
||||||
switch (ftdmchan->state) {
|
switch (ftdmchan->state) {
|
||||||
|
@ -1940,6 +2295,12 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_ss7_span_config)
|
||||||
return FTDM_FAIL;
|
return FTDM_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* create an peer channel queue for this span */
|
||||||
|
if ((ftdm_queue_create(&(ss7_span_info)->peer_chans, SPAN_PENDING_CHANS_QUEUE_SIZE)) != FTDM_SUCCESS) {
|
||||||
|
SS7_CRITICAL("Unable to create peer chans queue!\n");
|
||||||
|
return FTDM_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
/*setup the span structure with the info so far */
|
/*setup the span structure with the info so far */
|
||||||
g_ftdm_sngss7_data.sig_cb = sig_cb;
|
g_ftdm_sngss7_data.sig_cb = sig_cb;
|
||||||
span->start = ftdm_sangoma_ss7_start;
|
span->start = ftdm_sangoma_ss7_start;
|
||||||
|
|
|
@ -81,8 +81,12 @@ typedef enum {
|
||||||
SNGSS7_STA_IND_EVENT,
|
SNGSS7_STA_IND_EVENT,
|
||||||
SNGSS7_SUSP_IND_EVENT,
|
SNGSS7_SUSP_IND_EVENT,
|
||||||
SNGSS7_RESM_IND_EVENT,
|
SNGSS7_RESM_IND_EVENT,
|
||||||
SNGSS7_SSP_STA_CFM_EVENT
|
SNGSS7_SSP_STA_CFM_EVENT,
|
||||||
|
SNGSS7_INVALID_EVENT,
|
||||||
} sng_event_type_t;
|
} sng_event_type_t;
|
||||||
|
#define SNG_EVENT_TYPE_STRINGS "CON_IND", "CON_CFM", "CON_STA", "REL_IND", "REL_CFM", "DAT_IND", "FAC_IND", \
|
||||||
|
"FAC_CFM", "UMSG_IND", "STA_IND", "SUSP_IND", "RESM_IND", "SSP_STA_CFM", "INVALID"
|
||||||
|
FTDM_STR2ENUM_P(ftdm_str2sngss7_event, ftdm_sngss7_event2str, sng_event_type_t)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SNG_BIT_A = (1 << 0),
|
SNG_BIT_A = (1 << 0),
|
||||||
|
@ -500,6 +504,7 @@ typedef struct sngss7_span_data {
|
||||||
sngss7_group_data_t rx_cgu;
|
sngss7_group_data_t rx_cgu;
|
||||||
sngss7_group_data_t tx_cgu;
|
sngss7_group_data_t tx_cgu;
|
||||||
ftdm_queue_t *event_queue;
|
ftdm_queue_t *event_queue;
|
||||||
|
ftdm_queue_t *peer_chans;
|
||||||
} sngss7_span_data_t;
|
} sngss7_span_data_t;
|
||||||
|
|
||||||
typedef struct sngss7_event_data
|
typedef struct sngss7_event_data
|
||||||
|
|
|
@ -58,45 +58,39 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
|
||||||
|
|
||||||
var = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "sigbridge_peer");
|
var = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "sigbridge_peer");
|
||||||
if (!ftdm_strlen_zero(var)) {
|
if (!ftdm_strlen_zero(var)) {
|
||||||
ftdm_status_t status = FTDM_SUCCESS;
|
|
||||||
int rc = 0;
|
|
||||||
ftdm_span_t *peer_span = NULL;
|
ftdm_span_t *peer_span = NULL;
|
||||||
ftdm_channel_t *peer_chan = NULL;
|
ftdm_channel_t *peer_chan = NULL;
|
||||||
sngss7_chan_data_t *peer_info = NULL;
|
sngss7_chan_data_t *peer_info = NULL;
|
||||||
unsigned peer_span_id = 0;
|
|
||||||
unsigned peer_chan_id = 0;
|
ftdm_get_channel_from_string(var, &peer_span, &peer_chan);
|
||||||
rc = sscanf(var, "%u:%u", &peer_span_id, &peer_chan_id);
|
if (!peer_chan) {
|
||||||
if (rc != 2) {
|
SS7_ERROR_CHAN(ftdmchan, "Failed to find sigbridge peer from string '%s'\n", var);
|
||||||
SS7_ERROR_CHAN(ftdmchan, "Failed to parse sigbridge_peer string '%s'\n", var);
|
|
||||||
} else {
|
} else {
|
||||||
status = ftdm_span_find(peer_span_id, &peer_span);
|
if (peer_span->signal_type != FTDM_SIGTYPE_SS7) {
|
||||||
if (status != FTDM_SUCCESS || !peer_span) {
|
SS7_ERROR_CHAN(ftdmchan, "Peer channel '%s' has different signaling type %d'\n",
|
||||||
SS7_ERROR_CHAN(ftdmchan, "Failed to find peer span for channel id '%u:%u'\n", peer_span_id, peer_chan_id);
|
var, peer_span->signal_type);
|
||||||
} else if (peer_span->signal_type != FTDM_SIGTYPE_SS7) {
|
|
||||||
SS7_ERROR_CHAN(ftdmchan, "Peer channel %d:%d has different signaling type %d'\n",
|
|
||||||
peer_span_id, peer_chan_id, peer_span->signal_type);
|
|
||||||
} else {
|
} else {
|
||||||
if (peer_chan_id > (FTDM_MAX_CHANNELS_SPAN+1) || !(peer_chan = peer_span->channels[peer_chan_id])) {
|
sngss7_event_data_t *event_clone = NULL;
|
||||||
SS7_ERROR_CHAN(ftdmchan, "Invalid peer channel id '%u:%u'\n", peer_span_id, peer_chan_id);
|
peer_info = peer_chan->call_data;
|
||||||
} else {
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Starting native bridge with peer CIC %d\n",
|
||||||
sngss7_event_data_t *event_clone = NULL;
|
sngss7_info->circuit->cic, peer_info->circuit->cic);
|
||||||
peer_info = peer_chan->call_data;
|
/* make each one of us aware of the native bridge */
|
||||||
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Starting native bridge with peer CIC %d\n",
|
peer_info->peer_data = sngss7_info;
|
||||||
sngss7_info->circuit->cic, peer_info->circuit->cic);
|
sngss7_info->peer_data = peer_info;
|
||||||
/* make each one of us aware of the native bridge */
|
/* flush our own queue */
|
||||||
peer_info->peer_data = sngss7_info;
|
while ((event_clone = ftdm_queue_dequeue(sngss7_info->event_queue))) {
|
||||||
sngss7_info->peer_data = peer_info;
|
SS7_WARN("[CIC:%d]Discarding clone event from past call!\n", sngss7_info->circuit->cic);
|
||||||
/* flush our own queue */
|
ftdm_safe_free(event_clone);
|
||||||
while ((event_clone = ftdm_queue_dequeue(sngss7_info->event_queue))) {
|
|
||||||
SS7_WARN("[CIC:%d]Discarding clone event from past call!\n", sngss7_info->circuit->cic);
|
|
||||||
ftdm_safe_free(event_clone);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/* go up until release comes, note that state processing is done different and much simpler when there is a peer */
|
||||||
|
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
|
||||||
|
ftdm_channel_advance_states(ftdmchan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sngss7_info->peer_data) {
|
if (sngss7_info->peer_data) {
|
||||||
|
sngss7_span_data_t *span_data = ftdmchan->span->signal_data;
|
||||||
sngss7_event_data_t *event_clone = ftdm_queue_dequeue(sngss7_info->peer_data->event_queue);
|
sngss7_event_data_t *event_clone = ftdm_queue_dequeue(sngss7_info->peer_data->event_queue);
|
||||||
/* Retrieve IAM from our peer */
|
/* Retrieve IAM from our peer */
|
||||||
if (!event_clone) {
|
if (!event_clone) {
|
||||||
|
@ -108,6 +102,9 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
|
||||||
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged)\n", sngss7_info->circuit->cic);
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged)\n", sngss7_info->circuit->cic);
|
||||||
memcpy(&iam, &event_clone->event.siConEvnt, sizeof(iam));
|
memcpy(&iam, &event_clone->event.siConEvnt, sizeof(iam));
|
||||||
}
|
}
|
||||||
|
/* since this is the first time we dequeue an event from the peer, make sure our main thread process any other events,
|
||||||
|
this will trigger the interrupt in our span peer_chans queue which will wake up our main thread if it is sleeping */
|
||||||
|
ftdm_queue_enqueue(span_data->peer_chans, sngss7_info->peer_data->ftdmchan);
|
||||||
} else if (sngss7_info->circuit->transparent_iam &&
|
} else if (sngss7_info->circuit->transparent_iam &&
|
||||||
sngss7_retrieve_iam(ftdmchan, &iam) == FTDM_SUCCESS) {
|
sngss7_retrieve_iam(ftdmchan, &iam) == FTDM_SUCCESS) {
|
||||||
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Transparent)\n", sngss7_info->circuit->cic);
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Transparent)\n", sngss7_info->circuit->cic);
|
||||||
|
@ -322,10 +319,10 @@ void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan)
|
||||||
|
|
||||||
/* send the REL request to LibSngSS7 */
|
/* send the REL request to LibSngSS7 */
|
||||||
sng_cc_rel_request (1,
|
sng_cc_rel_request (1,
|
||||||
sngss7_info->suInstId,
|
sngss7_info->suInstId,
|
||||||
sngss7_info->spInstId,
|
sngss7_info->spInstId,
|
||||||
sngss7_info->circuit->id,
|
sngss7_info->circuit->id,
|
||||||
&rel);
|
&rel);
|
||||||
|
|
||||||
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx REL cause=%d \n",
|
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx REL cause=%d \n",
|
||||||
sngss7_info->circuit->cic,
|
sngss7_info->circuit->cic,
|
||||||
|
|
|
@ -130,6 +130,9 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SPAN_PENDING_CHANS_QUEUE_SIZE 1000
|
||||||
|
#define SPAN_PENDING_SIGNALS_QUEUE_SIZE 1000
|
||||||
|
|
||||||
#define GOTO_STATUS(label,st) status = st; goto label ;
|
#define GOTO_STATUS(label,st) status = st; goto label ;
|
||||||
|
|
||||||
#define ftdm_copy_string(x,y,z) strncpy(x, y, z - 1)
|
#define ftdm_copy_string(x,y,z) strncpy(x, y, z - 1)
|
||||||
|
@ -686,6 +689,9 @@ FT_DECLARE(ftdm_status_t) ftdm_sigmsg_remove_var(ftdm_sigmsg_t *sigmsg, const ch
|
||||||
*/
|
*/
|
||||||
FT_DECLARE(ftdm_status_t) ftdm_sigmsg_set_raw_data(ftdm_sigmsg_t *sigmsg, void *data, ftdm_size_t datalen);
|
FT_DECLARE(ftdm_status_t) ftdm_sigmsg_set_raw_data(ftdm_sigmsg_t *sigmsg, void *data, ftdm_size_t datalen);
|
||||||
|
|
||||||
|
/*! \brief Retrieve a span and channel data structure from a string in the format 'span_id:chan_id'*/
|
||||||
|
FT_DECLARE(ftdm_status_t) ftdm_get_channel_from_string(const char *string_id, ftdm_span_t **out_span, ftdm_channel_t **out_channel);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Assert condition
|
\brief Assert condition
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -265,6 +265,8 @@ typedef enum {
|
||||||
#define FTDM_CHANNEL_BLOCKING (1ULL << 35)
|
#define FTDM_CHANNEL_BLOCKING (1ULL << 35)
|
||||||
/*!< Media is digital */
|
/*!< Media is digital */
|
||||||
#define FTDM_CHANNEL_DIGITAL_MEDIA (1ULL << 36)
|
#define FTDM_CHANNEL_DIGITAL_MEDIA (1ULL << 36)
|
||||||
|
/*!< Native signaling bridge is enabled */
|
||||||
|
#define FTDM_CHANNEL_NATIVE_SIGBRIDGE (1ULL << 37)
|
||||||
|
|
||||||
#include "ftdm_state.h"
|
#include "ftdm_state.h"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue