diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c index 5f2beee65b..20b2199f21 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c @@ -545,6 +545,7 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; sngss7_event_data_t *event_clone = NULL; + int clone_event = 0; /* get the ftdmchan and ss7_chan_data from the circuit */ if (extract_chan_data(sngss7_event->circuit, &sngss7_info, &ftdmchan)) { @@ -560,11 +561,16 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev if (sngss7_event->event_id == SNGSS7_CON_IND_EVENT) { /* this is the first event in a call, flush the event queue */ - while ((event_clone = ftdm_queue_dequeue(sngss7_info->event_queue))) { - ftdm_safe_free(event_clone); - } + sngss7_flush_queue(sngss7_info->event_queue); /* clear the peer if any */ sngss7_info->peer_data = NULL; + clone_event++; + } + + /* if the call has already started and the event is not a release confirmation, clone the event */ + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED) && + sngss7_event->event_id != SNGSS7_REL_CFM_EVENT) { + clone_event++; } if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) { @@ -586,7 +592,7 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev } /* clone the event and save it for later usage, we do not clone RLC messages */ - if (sngss7_event->event_id != SNGSS7_REL_CFM_EVENT) { + if (clone_event) { event_clone = ftdm_calloc(1, sizeof(*sngss7_event)); if (event_clone) { memcpy(event_clone, sngss7_event, sizeof(*sngss7_event)); @@ -1002,6 +1008,7 @@ static ftdm_status_t ftdm_sangoma_ss7_native_bridge_state_change(ftdm_channel_t ftdm_channel_t *close_chan = ftdmchan; sngss7_clear_ckt_flag(sngss7_info, FLAG_SUS_RECVD); sngss7_clear_ckt_flag(sngss7_info, FLAG_T6_CANCELED); + sngss7_flush_queue(sngss7_info->event_queue); ftdm_channel_close (&close_chan); } break; @@ -1517,6 +1524,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t *ftdmchan) /* close the channel */ SS7_DEBUG_CHAN(ftdmchan,"FTDM Channel Close %s\n", ""); + sngss7_flush_queue(sngss7_info->event_queue); ftdm_channel_close (&close_chan); } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h index c77599d3d9..fb60183bf8 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h @@ -57,7 +57,7 @@ #define SNGSS7_EVENT_QUEUE_SIZE 100 #define SNGSS7_PEER_CHANS_QUEUE_SIZE 100 -#define SNGSS7_CHAN_EVENT_QUEUE_SIZE 5 +#define SNGSS7_CHAN_EVENT_QUEUE_SIZE 100 #define MAX_SIZEOF_SUBADDR_IE 24 /* as per Q931 4.5.9 */ @@ -65,6 +65,14 @@ (switchtype == LSI_SW_ANS92) || \ (switchtype == LSI_SW_ANS95) +#define sngss7_flush_queue(queue) \ + do { \ + void *__queue_data = NULL; \ + while ((__queue_data = ftdm_queue_dequeue(queue))) { \ + ftdm_safe_free(__queue_data); \ + } \ + } while (0) + typedef struct ftdm2trillium { uint8_t ftdm_val; uint8_t trillium_val; @@ -552,7 +560,7 @@ typedef enum { FLAG_INFID_PAUSED = (1 << 15), FLAG_SENT_ACM = (1 << 16), FLAG_SENT_CPG = (1 << 17), - FLAG_SUS_RECVD = (1 << 18), + FLAG_SUS_RECVD = (1 << 18), FLAG_T6_CANCELED = (1 << 19), FLAG_RELAY_DOWN = (1 << 30), FLAG_CKT_RECONFIG = (1 << 31) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c index 20e661d73e..00d06905dd 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c @@ -70,17 +70,17 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) SS7_ERROR_CHAN(ftdmchan, "Peer channel '%s' has different signaling type %d'\n", var, peer_span->signal_type); } else { - sngss7_event_data_t *event_clone = NULL; peer_info = peer_chan->call_data; SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Starting native bridge with peer CIC %d\n", sngss7_info->circuit->cic, peer_info->circuit->cic); + /* make each one of us aware of the native bridge */ peer_info->peer_data = sngss7_info; sngss7_info->peer_data = peer_info; + /* flush our own queue */ - while ((event_clone = ftdm_queue_dequeue(sngss7_info->event_queue))) { - ftdm_safe_free(event_clone); - } + sngss7_flush_queue(sngss7_info->event_queue); + /* 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);