diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 6f6025ac36..ef3989c19c 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -3543,7 +3543,83 @@ SWITCH_STANDARD_API(ft_function) goto end; } - if (!strcasecmp(argv[0], "dump")) { + if (!strcasecmp(argv[0], "sigstatus")) { + ftdm_span_t *span = NULL; + ftdm_signaling_status_t sigstatus; + + if (argc < 3) { + stream->write_function(stream, "-ERR Usage: ftdm sigstatus get|set [] [] []\n"); + goto end; + } + if (!strcasecmp(argv[1], "get") && argc < 3) { + stream->write_function(stream, "-ERR sigstatus get usage: get \n"); + goto end; + } + if (!strcasecmp(argv[1], "set") && argc != 5) { + stream->write_function(stream, "-ERR sigstatus set usage: set |all \n"); + goto end; + } + + ftdm_span_find_by_name(argv[2], &span); + if (!span) { + stream->write_function(stream, "-ERR invalid span\n"); + goto end; + } + + if (!strcasecmp(argv[1], "get")) { + if (argc == 4) { + uint32_t chan_id = atol(argv[3]); + ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id); + if (!fchan) { + stream->write_function(stream, "-ERR failed to get channel id '%d'\n", chan_id); + goto end; + } + + if ((FTDM_SUCCESS == ftdm_channel_get_sig_status(fchan, &sigstatus))) { + stream->write_function(stream, "channel %d signaling status: %s\n", chan_id, ftdm_signaling_status2str(sigstatus)); + } else { + stream->write_function(stream, "-ERR failed to get channel sigstatus\n"); + } + goto end; + } else { + if ((FTDM_SUCCESS == ftdm_span_get_sig_status(span, &sigstatus))) { + stream->write_function(stream, "signaling_status: %s\n", ftdm_signaling_status2str(sigstatus)); + } else { + stream->write_function(stream, "-ERR failed to read span status: %s\n", ftdm_span_get_last_error(span)); + } + } + goto end; + } + if (!strcasecmp(argv[1], "set")) { + sigstatus = ftdm_str2ftdm_signaling_status(argv[4]); + + if (!strcasecmp(argv[3], "all")) { + if ((FTDM_SUCCESS == ftdm_span_set_sig_status(span, sigstatus))) { + stream->write_function(stream, "Signaling status of all channels from span %s set to %s\n", + ftdm_span_get_name(span), ftdm_signaling_status2str(sigstatus)); + } else { + stream->write_function(stream, "-ERR failed to set span sigstatus to '%s'\n", ftdm_signaling_status2str(sigstatus)); + } + goto end; + } else { + uint32_t chan_id = atol(argv[3]); + ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id); + if (!fchan) { + stream->write_function(stream, "-ERR failed to get channel id '%d'\n", chan_id); + goto end; + } + + if ((FTDM_SUCCESS == ftdm_channel_set_sig_status(fchan, sigstatus))) { + stream->write_function(stream, "Signaling status of channel %d set to %s\n", chan_id, + ftdm_signaling_status2str(sigstatus)); + } else { + stream->write_function(stream, "-ERR failed to set span sigstatus to '%s'\n", ftdm_signaling_status2str(sigstatus)); + } + goto end; + } + } + + } else if (!strcasecmp(argv[0], "dump")) { if (argc < 2) { stream->write_function(stream, "-ERR Usage: ftdm dump []\n"); goto end; diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 49ccf64506..9f35971abb 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -55,10 +55,13 @@ static int32_t g_thread_count = 0; typedef int openr2_call_status_t; -/* when the users kills a span we clear this flag to kill the signaling thread */ +/* when the user stops a span, we clear FTDM_R2_SPAN_STARTED, so that the signaling thread + * knows it must stop, and we wait for FTDM_R2_RUNNING to be clear, which tells us the + * signaling thread is done. */ /* FIXME: what about the calls that are already up-and-running? */ typedef enum { FTDM_R2_RUNNING = (1 << 0), + FTDM_R2_SPAN_STARTED = (1 << 1), } ftdm_r2_flag_t; /* private call information stored in ftdmchan->call_data void* ptr, @@ -424,13 +427,14 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call) static ftdm_status_t ftdm_r2_start(ftdm_span_t *span) { ftdm_r2_data_t *r2_data = span->signal_data; - ftdm_set_flag(r2_data, FTDM_R2_RUNNING); + ftdm_set_flag(r2_data, FTDM_R2_SPAN_STARTED); return ftdm_thread_create_detached(ftdm_r2_run, span); } static ftdm_status_t ftdm_r2_stop(ftdm_span_t *span) { ftdm_r2_data_t *r2_data = span->signal_data; + ftdm_clear_flag(r2_data, FTDM_R2_SPAN_STARTED); while (ftdm_test_flag(r2_data, FTDM_R2_RUNNING)) { ftdm_log(FTDM_LOG_DEBUG, "Waiting for R2 span %s\n", span->name); ftdm_sleep(100); @@ -461,12 +465,74 @@ static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_channel_sig_status) openr2_chan_set_idle(r2chan); break; default: - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%s'\n", status); + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status); return FTDM_FAIL; } return FTDM_SUCCESS; } +static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_span_sig_status) +{ + ftdm_iterator_t *citer = NULL; + ftdm_iterator_t *chaniter = ftdm_span_get_chan_iterator(span, NULL); + if (!chaniter) { + ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); + return FTDM_FAIL; + } + /* if ALL channels are non-idle, report SUSPENDED. UP otherwise. */ + *status = FTDM_SIG_STATE_SUSPENDED; + for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) { + ftdm_channel_t *fchan = ftdm_iterator_current(citer); + if (ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP)) { + *status = FTDM_SIG_STATE_UP; + break; + } + } + ftdm_iterator_free(chaniter); + return FTDM_SUCCESS; +} + +static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_span_sig_status) +{ + ftdm_iterator_t *chaniter = NULL; + ftdm_iterator_t *citer = NULL; + uint32_t span_opr = -1; + + /* we either set the channels to BLOCK or IDLE */ + switch(status) { + case FTDM_SIG_STATE_DOWN: + case FTDM_SIG_STATE_SUSPENDED: + span_opr = 0; + break; + case FTDM_SIG_STATE_UP: + span_opr = 1; + break; + default: + ftdm_log(FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status); + return FTDM_FAIL; + } + + chaniter = ftdm_span_get_chan_iterator(span, NULL); + if (!chaniter) { + ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); + return FTDM_FAIL; + } + /* iterate over all channels, setting them to the requested state */ + for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) { + ftdm_channel_t *fchan = ftdm_iterator_current(citer); + openr2_chan_t *r2chan = R2CALL(fchan)->r2chan; + if (span_opr == 0) { + openr2_chan_set_blocked(r2chan); + ftdm_log_chan_msg(fchan, FTDM_LOG_NOTICE, "Channel blocked\n"); + } else { + openr2_chan_set_idle(r2chan); + ftdm_log_chan_msg(fchan, FTDM_LOG_NOTICE, "Channel idle\n"); + } + } + ftdm_iterator_free(chaniter); + return FTDM_SUCCESS; +} + /* always called from the monitor thread */ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan) { @@ -1441,6 +1507,8 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling) span->signal_type = FTDM_SIGTYPE_R2; span->signal_data = r2data; span->outgoing_call = r2_outgoing_call; + span->get_span_sig_status = ftdm_r2_get_span_sig_status; + span->set_span_sig_status = ftdm_r2_set_span_sig_status; span->get_channel_sig_status = ftdm_r2_get_channel_sig_status; span->set_channel_sig_status = ftdm_r2_set_channel_sig_status; @@ -1690,6 +1758,9 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) uint32_t txqueue_size = 4; short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count); + /* as long as this thread is running, this flag is set */ + ftdm_set_flag(r2data, FTDM_R2_RUNNING); + #ifdef __linux__ r2data->monitor_thread_id = syscall(SYS_gettid); #endif @@ -1712,7 +1783,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) memset(&start, 0, sizeof(start)); memset(&end, 0, sizeof(end)); - while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_RUNNING)) { + while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_SPAN_STARTED)) { res = gettimeofday(&end, NULL); if (res) { ftdm_log(FTDM_LOG_CRIT, "Failure gettimeofday [%s]\n", strerror(errno)); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index 132a675769..087845f857 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -167,6 +167,7 @@ typedef struct sngisdn_chan_data { uint32_t flags; uint8_t ces; /* used only for BRI, otherwise always 0 */ uint8_t dchan_id; + uint16_t call_ref; /* Q.931 call reference, only valid for ETSI/INSNET/QSIG */ uint32_t suInstId; /* instance ID generated locally */ uint32_t spInstId; /* instance ID generated by stack */ @@ -380,6 +381,9 @@ void sngisdn_rcv_cc_ind(CcMngmt *status); void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...); void sngisdn_rcv_sng_assert(char *message); +#ifdef NETBORDER_CALL_REF +ftdm_status_t get_callref(ftdm_channel_t *ftdmchan, BCCallRef* callRef); +#endif ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb); ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb); ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index 7e9e360c6d..67bc6e9661 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -71,13 +71,12 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */ sngisdn_info->glare.spInstId = spInstId; sngisdn_info->glare.dChan = dChan; - sngisdn_info->glare.ces = ces; + sngisdn_info->glare.ces = ces; break; } sngisdn_info->suInstId = get_unique_suInstId(suId); sngisdn_info->spInstId = spInstId; - if (conEvnt->cdPtyNmb.eh.pres && signal_data->num_local_numbers) { uint8_t local_number_matched = 0; @@ -125,6 +124,9 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) } /* Fill in call information */ +#ifdef NETBORDER_CALL_REF + get_callref(ftdmchan, &conEvnt->callRef); +#endif get_calling_num(ftdmchan, &conEvnt->cgPtyNmb); get_calling_num2(ftdmchan, &conEvnt->cgPtyNmb2); get_called_num(ftdmchan, &conEvnt->cdPtyNmb); @@ -282,6 +284,7 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event) case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: case FTDM_CHANNEL_STATE_DIALING: + get_callref(ftdmchan, &cnStEvnt->callRef); get_prog_ind_ie(ftdmchan, &cnStEvnt->progInd); get_facility_ie(ftdmchan, &cnStEvnt->facilityStr); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); @@ -354,6 +357,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) case MI_CALLPROC: case MI_PROGRESS: case MI_ALERTING: + get_callref(ftdmchan, &cnStEvnt->callRef); get_prog_ind_ie(ftdmchan, &cnStEvnt->progInd); get_facility_ie(ftdmchan, &cnStEvnt->facilityStr); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index c6c59bb9fd..ba8224f75b 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -161,6 +161,32 @@ ftdm_status_t sngisdn_set_span_avail_rate(ftdm_span_t *span, sngisdn_avail_t ava return FTDM_SUCCESS; } +#ifdef NETBORDER_CALL_REF +ftdm_status_t get_callref(ftdm_channel_t *ftdmchan, BCCallRef* callRef) +{ + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; + sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; + + if (signal_data->raw_trace_q931) { + if (callRef->eh.pres != PRSNT_NODEF || callRef->reference.pres != PRSNT_NODEF) { + /* Netborder only supports BRI, so we only care for BRI for now */ + if (FTDM_SPAN_IS_BRI(ftdmchan->span) && !sngisdn_info->call_ref) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to obtain call reference\n"); + } + return FTDM_FAIL; + } + if (FTDM_SPAN_IS_BRI(ftdmchan->span)) { + sngisdn_info->call_ref = 0x7F & callRef->reference.val; + } else { + sngisdn_info->call_ref = 0x7FFF & callRef->reference.val; + } + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Call reference:%04x\n", sngisdn_info->call_ref); + } + return FTDM_SUCCESS; +} +#endif + ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) { ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c index fd9edeba8d..e63ed16a77 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c @@ -38,14 +38,26 @@ #define OCTET(x) (ieData[x-1] & 0xFF) #define MAX_DECODE_STR_LEN 2000 +typedef struct sngisdn_trace_info +{ + uint8_t call_ref_flag; + uint16_t call_ref; + uint8_t msgtype; + uint8_t bchan_no; + ftdm_trace_dir_t dir; +} sngisdn_frame_info_t; + void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end); uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start); +static ftdm_status_t sngisdn_map_call(sngisdn_span_data_t *signal_data, sngisdn_frame_info_t frame_info, ftdm_channel_t **found); +static ftdm_status_t sngisdn_get_frame_info(uint8_t *data, uint32_t data_len, ftdm_trace_dir_t dir, sngisdn_frame_info_t *frame_info); uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi); char* get_code_2_str(int code, struct code2str *pCodeTable); void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len); void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len); + char* get_code_2_str(int code, struct code2str *pCodeTable) { struct code2str* pCode2txt; @@ -121,9 +133,6 @@ void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t d sigev.ev_data.trace.dir = dir; sigev.ev_data.trace.type = FTDM_TRACE_TYPE_Q921; - /* TODO: Map trace to call ID here */ - sigev.call_id = 0; - raw_data = ftdm_malloc(data_len); ftdm_assert(raw_data, "Failed to malloc"); @@ -218,26 +227,33 @@ void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t d { uint8_t *raw_data; ftdm_sigmsg_t sigev; + ftdm_channel_t *ftdmchan; + sngisdn_frame_info_t frame_info; memset(&sigev, 0, sizeof(sigev)); - sigev.span_id = signal_data->ftdm_span->span_id; - sigev.chan_id = signal_data->dchan->chan_id; - sigev.channel = signal_data->dchan; - sigev.event_id = FTDM_SIGEVENT_TRACE_RAW; + /* Note: Mapped raw trace assume only exclusive b-channel selection is used. i.e the b-channel selected on outgoing SETUP is always used for the call */ + + if (sngisdn_get_frame_info(data, data_len, dir, &frame_info) == FTDM_SUCCESS) { + if (sngisdn_map_call(signal_data, frame_info, &ftdmchan) == FTDM_SUCCESS) { + sigev.call_id = ftdmchan->caller_data.call_id; + sigev.span_id = ftdmchan->physical_span_id; + sigev.chan_id = ftdmchan->physical_chan_id; + sigev.channel = ftdmchan; + } + sigev.event_id = FTDM_SIGEVENT_TRACE_RAW; - sigev.ev_data.trace.dir = dir; - sigev.ev_data.trace.type = FTDM_TRACE_TYPE_Q931; - - /* TODO: Map trace to call ID here */ - - raw_data = ftdm_malloc(data_len); - ftdm_assert(raw_data, "Failed to malloc"); - - memcpy(raw_data, data, data_len); - sigev.raw_data = raw_data; - sigev.raw_data_len = data_len; - ftdm_span_send_signal(signal_data->ftdm_span, &sigev); + sigev.ev_data.trace.dir = dir; + sigev.ev_data.trace.type = FTDM_TRACE_TYPE_Q931; + + raw_data = ftdm_malloc(data_len); + ftdm_assert(raw_data, "Failed to malloc"); + + memcpy(raw_data, data, data_len); + sigev.raw_data = raw_data; + sigev.raw_data_len = data_len; + ftdm_span_send_signal(signal_data->ftdm_span, &sigev); + } } void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len) @@ -253,9 +269,6 @@ void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len) prot_disc = (uint8_t)data[0]; str_len += sprintf(&str[str_len], " Prot Disc:%s (0x%02x)\n", get_code_2_str(prot_disc, dcodQ931ProtDiscTable), prot_disc); - - - /* Decode Call Reference */ lenCallRef = (uint8_t) (data[1] & 0x0F); @@ -747,4 +760,203 @@ void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_ return; } +static ftdm_status_t sngisdn_get_frame_info(uint8_t *data, uint32_t data_len, ftdm_trace_dir_t dir, sngisdn_frame_info_t *target) +{ + uint8_t pos = 0; + uint8_t flag; + uint16_t ref = 0; + uint8_t ref_len = 0; + uint8_t bchan_no = 0; + uint8_t msgtype; + + /* First octet is protocol discriminator */ + pos++; + /* Second octet contains length of call reference */ + ref_len = data[pos++] & 0x0F; + + /* third octet is call reference */ + flag = (data[pos] & 0x80) >> 7; + if (ref_len == 2) { + ref = (data[pos++] & 0x7F) << 8; + ref |= (data[pos++] & 0xFF) ; + } else { + ref = (data[pos++] & 0x7F); + } + + /* Next octet is the message type */ + msgtype = data[pos++] & 0x7F; + + /* + ftdm_log(FTDM_LOG_DEBUG, "Raw frame:call_ref:0x%04x flag:%d msgtype:%d\n", ref, flag, msgtype); + */ + if (!ref) { + /* This is not a call specific message (RESTART for example and we do not care about it) */ + return FTDM_FAIL; + } + + /* Look for the b-channel */ + if (msgtype == PROT_Q931_MSGTYPE_SETUP) { + /* Try to find the b-channel no*/ + + for(; pos < data_len; pos++) { + uint8_t ie_id = data[pos]; + uint8_t ie_len = data[pos+1]; + + switch(ie_id) { + case PROT_Q931_IE_SENDING_COMPLETE: + /* Single octet ie's do not have a length */ + ie_len = 0; + break; + case PROT_Q931_IE_CHANNEL_ID: + { + /* Try to obtain the b-channel */ + uint8_t ie_pos = pos+2; + //ifaceIdPresent = get_bits(OCTET(3),7,7); + if (data[ie_pos] & 0x20) { + /* Interface type is Primary Rate */ + ie_pos+=2; + bchan_no = data[ie_pos] & 0x7F; + } else { + /* Interface type is Basic Interface */ + /* Get the channel number from info channel selection */ + bchan_no = data[ie_pos] & 0x03; + } + ftdm_log(FTDM_LOG_DEBUG, "Found b-channel:%d\n", bchan_no); + goto parse_ies_done; + } + break; + default: + pos = pos+ie_len+1; + } + //ftdm_log(FTDM_LOG_DEBUG, "Decoded IE:%s\n", get_code_2_str(ie_id, dcodQ931IEIDTable)); + } + if (!bchan_no) { + char tmp[1000]; + print_hex_dump(tmp, 0, data, 0, data_len); + ftdm_log(FTDM_LOG_WARNING, "Failed to determine b-channel on SETUP message\n%s\n", tmp); + } + } + +parse_ies_done: + + target->call_ref = ref; + target->call_ref_flag = flag; + target->msgtype = msgtype; + target->bchan_no = bchan_no; + target->dir = dir; + + return FTDM_SUCCESS; +} + +static ftdm_status_t sngisdn_map_call(sngisdn_span_data_t *signal_data, sngisdn_frame_info_t frame_info, ftdm_channel_t **found) +{ + ftdm_channel_t *ftdmchan; + sngisdn_chan_data_t *sngisdn_info; + ftdm_iterator_t *chaniter = NULL; + ftdm_iterator_t *curr = NULL; + ftdm_status_t status = FTDM_FAIL; + uint8_t outbound_call = 0; + + if ((!frame_info.call_ref_flag && frame_info.dir == FTDM_TRACE_DIR_OUTGOING) || + (frame_info.call_ref_flag && frame_info.dir == FTDM_TRACE_DIR_INCOMING)) { + + /* If this is an outgoing frame and this frame was sent by the originating side + of the call (frame_info.call_ref_flag == 0), then this is an outbound call */ + outbound_call = 1; + } else { + outbound_call = 0; + } + + switch (frame_info.msgtype) { + case PROT_Q931_MSGTYPE_SETUP: + /* We initiated this outgoing call try to match the call reference with our internal call-id*/ + if (!frame_info.bchan_no) { + /* We were not able to determine the bchannel on this call, so we will not be able to match it anyway */ + status = FTDM_FAIL; + } + + chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL); + for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { + ftdmchan = (ftdm_channel_t*)(ftdm_iterator_current(curr)); + ftdm_channel_lock(ftdmchan); + + if (outbound_call) { + sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data; + if (sngisdn_info && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { + if (ftdmchan->caller_data.call_id && ftdmchan->physical_chan_id == frame_info.bchan_no) { + + sngisdn_info->call_ref = frame_info.call_ref; + *found = ftdmchan; + status = FTDM_SUCCESS; + } + } + } else { + if (ftdmchan->physical_chan_id == frame_info.bchan_no) { + *found = ftdmchan; + status = FTDM_SUCCESS; + } + } + ftdm_channel_unlock(ftdmchan); + } + ftdm_iterator_free(chaniter); + break; + case PROT_Q931_MSGTYPE_ALERTING: + case PROT_Q931_MSGTYPE_PROCEEDING: + case PROT_Q931_MSGTYPE_PROGRESS: + case PROT_Q931_MSGTYPE_CONNECT: + case PROT_Q931_MSGTYPE_SETUP_ACK: + case PROT_Q931_MSGTYPE_CONNECT_ACK: + case PROT_Q931_MSGTYPE_USER_INFO: + case PROT_Q931_MSGTYPE_DISCONNECT: + case PROT_Q931_MSGTYPE_RELEASE: + case PROT_Q931_MSGTYPE_RELEASE_ACK: + case PROT_Q931_MSGTYPE_RELEASE_COMPLETE: + case PROT_Q931_MSGTYPE_FACILITY: + case PROT_Q931_MSGTYPE_NOTIFY: + case PROT_Q931_MSGTYPE_STATUS_ENQUIRY: + case PROT_Q931_MSGTYPE_INFORMATION: + case PROT_Q931_MSGTYPE_STATUS: + /* Look for an outbound call on that span and and try to match the call-id */ + chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL); + for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { + ftdmchan = (ftdm_channel_t*)(ftdm_iterator_current(curr)); + ftdm_channel_lock(ftdmchan); + sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data; + if (outbound_call) { + if (sngisdn_info && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { + if (sngisdn_info->call_ref == frame_info.call_ref) { + + *found = ftdmchan; + status = FTDM_SUCCESS; + } + } + } else { + if (sngisdn_info && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { + if (sngisdn_info->call_ref && sngisdn_info->call_ref == frame_info.call_ref) { + + *found = ftdmchan; + status = FTDM_SUCCESS; + } + } + } + ftdm_channel_unlock(ftdmchan); + } + ftdm_iterator_free(chaniter); + break; + default: + /* This frame is not call specific, ignore */ + break; + } + if (status == FTDM_SUCCESS) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Mapped %s with Call Ref:%04x to call-id:%d\n", get_code_2_str(frame_info.msgtype, dcodQ931MsgTypeTable), frame_info.call_ref, (*found)->caller_data.call_id); + } else { + /* We could not map this frame to a call-id */ + ftdm_log(FTDM_LOG_DEBUG, "Failed to map %s with Call Ref:%04x to local call\n", + get_code_2_str(frame_info.msgtype, dcodQ931MsgTypeTable), frame_info.call_ref); + } + + return status; +} + + diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h index f054de9377..db33cf8083 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h @@ -191,37 +191,65 @@ struct code2str dcodQ931CallRefLoTable[] = { {13, "D"}, {14, "E"}, {15, "F"}, - {-1,"?"}, + {-1, "?"}, }; +#define PROT_Q931_MSGTYPE_ALERTING 1 +#define PROT_Q931_MSGTYPE_PROCEEDING 2 +#define PROT_Q931_MSGTYPE_PROGRESS 3 +#define PROT_Q931_MSGTYPE_SETUP 5 +#define PROT_Q931_MSGTYPE_CONNECT 7 +#define PROT_Q931_MSGTYPE_SETUP_ACK 13 +#define PROT_Q931_MSGTYPE_CONNECT_ACK 15 +#define PROT_Q931_MSGTYPE_USER_INFO 32 +#define PROT_Q931_MSGTYPE_SUSPEND_REJ 33 +#define PROT_Q931_MSGTYPE_RESUME_REJ 34 +#define PROT_Q931_MSGTYPE_SUSPEND 37 +#define PROT_Q931_MSGTYPE_RESUME 38 +#define PROT_Q931_MSGTYPE_SUSPEND_ACK 45 +#define PROT_Q931_MSGTYPE_RESUME_ACK 46 +#define PROT_Q931_MSGTYPE_DISCONNECT 69 +#define PROT_Q931_MSGTYPE_RESTART 70 +#define PROT_Q931_MSGTYPE_RELEASE 77 +#define PROT_Q931_MSGTYPE_RELEASE_ACK 78 +#define PROT_Q931_MSGTYPE_RELEASE_COMPLETE 90 +#define PROT_Q931_MSGTYPE_SEGMENT 96 +#define PROT_Q931_MSGTYPE_FACILITY 98 +#define PROT_Q931_MSGTYPE_NOTIFY 110 +#define PROT_Q931_MSGTYPE_STATUS_ENQUIRY 117 +#define PROT_Q931_MSGTYPE_CONGESTION_CNTRL 121 +#define PROT_Q931_MSGTYPE_INFORMATION 123 +#define PROT_Q931_MSGTYPE_STATUS 125 + + struct code2str dcodQ931MsgTypeTable[] = { - {1, "Alerting"}, - {2, "Call Proceeding"}, - {3, "Progress"}, - {5, "Setup"}, - {7, "Connect"}, - {13, "Setup Ack"}, - {15, "Connect Ack"}, - {32, "User Info"}, - {33, "Suspend Rej"}, - {34, "Resume Rej"}, - {37, "Suspend"}, - {38, "Resume"}, - {45, "Suspend Ack"}, - {46, "Resume Ack"}, - {69, "Disconnect"}, - {70, "Restart"}, - {77, "Release"}, - {78, "Release Ack"}, - {90, "Release Compl"}, - {96, "Segment"}, - {98, "Facility"}, - {110, "Notify"}, - {117, "Status Enquiry"}, - {121, "Congest Cntrl"}, - {123, "Information"}, - {125, "Status"}, - {-1, "Unknown"}, + {PROT_Q931_MSGTYPE_ALERTING, "ALERT"}, + {PROT_Q931_MSGTYPE_PROCEEDING, "PROCEED"}, + {PROT_Q931_MSGTYPE_PROGRESS, "PROGRESS"}, + {PROT_Q931_MSGTYPE_SETUP, "SETUP"}, + {PROT_Q931_MSGTYPE_CONNECT, "CONNECT"}, + {PROT_Q931_MSGTYPE_SETUP_ACK, "SETUP ACK"}, + {PROT_Q931_MSGTYPE_CONNECT_ACK, "CONNECT ACK"}, + {PROT_Q931_MSGTYPE_USER_INFO, "USER INFO"}, + {PROT_Q931_MSGTYPE_SUSPEND_REJ, "SUSPEND REJ"}, + {PROT_Q931_MSGTYPE_RESUME_REJ, "RESUME REJ"}, + {PROT_Q931_MSGTYPE_SUSPEND, "SUSPEND"}, + {PROT_Q931_MSGTYPE_RESUME, "RESUME"}, + {PROT_Q931_MSGTYPE_SUSPEND_ACK, "SUSPEND ACK"}, + {PROT_Q931_MSGTYPE_RESUME_ACK, "RESUME ACK"}, + {PROT_Q931_MSGTYPE_DISCONNECT, "DISCONNECT"}, + {PROT_Q931_MSGTYPE_RESTART, "RESTART"}, + {PROT_Q931_MSGTYPE_RELEASE, "RELEASE"}, + {PROT_Q931_MSGTYPE_RELEASE_ACK, "RELEASR ACK"}, + {PROT_Q931_MSGTYPE_RELEASE_COMPLETE, "RELEASE COMPLETE"}, + {PROT_Q931_MSGTYPE_SEGMENT, "SEGMENT"}, + {PROT_Q931_MSGTYPE_FACILITY, "FACILITY"}, + {PROT_Q931_MSGTYPE_NOTIFY, "NOTIFY"}, + {PROT_Q931_MSGTYPE_STATUS_ENQUIRY, "STATUS ENQ"}, + {PROT_Q931_MSGTYPE_CONGESTION_CNTRL, "CONGESTION CTRL"}, + {PROT_Q931_MSGTYPE_INFORMATION, "INFO"}, + {PROT_Q931_MSGTYPE_STATUS, "STATUS"}, + {-1, "UNKNOWN"}, }; struct code2str dcodQ931CauseCodeTable[] = {