From ed01944c15d93885aed94bd9e4f9cee86d8b4c86 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 22 Sep 2010 14:59:06 -0400 Subject: [PATCH 1/4] freetdm: add initial changes for FreeTDM channel history feature --- libs/freetdm/mod_freetdm/mod_freetdm.c | 7 ++- libs/freetdm/src/ftdm_io.c | 61 ++++++++++++++++++++ libs/freetdm/src/include/freetdm.h | 8 ++- libs/freetdm/src/include/private/ftdm_core.h | 11 ++++ 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index b4a40f0bad..f87545715a 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -3660,7 +3660,12 @@ SWITCH_STANDARD_API(ft_function) if(chan_id > ftdm_span_get_chan_count(span)) { stream->write_function(stream, "-ERR invalid channel\n"); } else { + char *dbgstr = NULL; + ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id); dump_chan(span, chan_id, stream); + dbgstr = ftdm_channel_get_history_str(fchan); + stream->write_function(stream, "%s\n", dbgstr); + ftdm_free(dbgstr); } } else { stream->write_function(stream, "+OK\n"); @@ -3989,7 +3994,7 @@ SWITCH_STANDARD_API(ft_function) if (rply) { stream->write_function(stream, "%s", rply); - free(rply); + ftdm_free(rply); } else { stream->write_function(stream, "-ERR Usage: %s\n", FT_SYNTAX); } diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 97aa01bca0..82997185f7 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -1293,6 +1293,16 @@ end: ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Changed state from %s to %s\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state)); ftdmchan->last_state = ftdmchan->state; ftdmchan->state = state; + ftdmchan->history[ftdmchan->hindex].file = file; + ftdmchan->history[ftdmchan->hindex].func = func; + ftdmchan->history[ftdmchan->hindex].line = line; + ftdmchan->history[ftdmchan->hindex].state = ftdmchan->state; + ftdmchan->history[ftdmchan->hindex].last_state = ftdmchan->last_state; + ftdmchan->history[ftdmchan->hindex].time = ftdm_current_time_in_ms(); + ftdmchan->hindex++; + if (ftdmchan->hindex == ftdm_array_len(ftdmchan->history)) { + ftdmchan->hindex = 0; + } ftdm_set_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); ftdm_mutex_lock(ftdmchan->span->mutex); @@ -5213,6 +5223,57 @@ FT_DECLARE(char *) ftdm_strndup(const char *str, ftdm_size_t inlen) return new; } +#define FTDM_DEBUG_LINE_LEN 255 +FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *fchan) +{ + uint8_t j = 0; + int written = 0; + char *buff = NULL; + uint8_t i = fchan->hindex; + + int dbglen = ftdm_array_len(fchan->history) * FTDM_DEBUG_LINE_LEN; + int len = dbglen; + + char *debugstr = ftdm_calloc(1, dbglen); + if (!debugstr) { + return NULL; + } + buff = debugstr; + + for (i = fchan->hindex; i < ftdm_array_len(fchan->history); i++) { + if (!fchan->history[i].file) { + break; + } + written = snprintf(buff, len, "%s -> %s at %s %s:%d\n", + ftdm_channel_state2str(fchan->history[i].last_state), ftdm_channel_state2str(fchan->history[i].state), fchan->history[i].func, + fchan->history[i].file, fchan->history[i].line); + if (written >= len) { + ftdm_free(debugstr); + ftdm_log(FTDM_LOG_ERROR, "Not enough memory to build debug history string\n"); + return NULL; + } + len -= written; + buff += written; + } + + for (j = 0; j < fchan->hindex; j++) { + written = snprintf(buff, len, "%s -> %s at %s %s:%d\n", + ftdm_channel_state2str(fchan->history[i].last_state), ftdm_channel_state2str(fchan->history[i].state), fchan->history[i].func, + fchan->history[i].file, fchan->history[i].line); + if (written >= len) { + ftdm_free(debugstr); + ftdm_log(FTDM_LOG_ERROR, "Not enough memory to build debug history string\n"); + return NULL; + } + len -= written; + buff += written; + } + + debugstr[dbglen-1] = 0; + + return debugstr; +} + /* For Emacs: * Local Variables: diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 1f50a2ccaa..f4a515b476 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -1277,7 +1277,13 @@ FT_DECLARE(const char *) ftdm_channel_get_state_str(const ftdm_channel_t *channe /*! \brief For display debugging purposes you can display this string which describes the last channel internal state */ FT_DECLARE(const char *) ftdm_channel_get_last_state_str(const ftdm_channel_t *channel); -/*! \brief For display debugging purposes you can display this string which describes the last channel internal state */ +/*! \brief For display debugging purposes you can display this string which describes the history of the channel + * \param The channel + * \return History string for the channel. You must free the string with ftdm_free + */ +FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *channel); + +/*! \brief Initialize channel state for an outgoing call */ FT_DECLARE(ftdm_status_t) ftdm_channel_init(ftdm_channel_t *ftdmchan); /*! \brief Initialize the library */ diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index a701c1383d..beee868633 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -356,6 +356,15 @@ typedef struct { } ftdm_dtmf_debug_t; #endif +typedef struct { + const char *file; + const char *func; + int line; + ftdm_channel_state_t state; + ftdm_channel_state_t last_state; + ftdm_time_t time; +} ftdm_channel_history_entry_t; + /* 2^8 table size, one for each byte (sample) value */ #define FTDM_GAINS_TABLE_SIZE 256 struct ftdm_channel { @@ -381,6 +390,8 @@ struct ftdm_channel { ftdm_channel_state_t state; ftdm_channel_state_t last_state; ftdm_channel_state_t init_state; + ftdm_channel_history_entry_t history[10]; + uint8_t hindex; ftdm_mutex_t *mutex; teletone_dtmf_detect_state_t dtmf_detect; uint32_t buffer_delay; From 640b81a27c6cffa927e9fd36bb3c0a9c3b0c4bfe Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 23 Sep 2010 07:38:58 -0400 Subject: [PATCH 2/4] freetdm: improve state debug dumping --- libs/freetdm/src/ftdm_io.c | 54 +++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 82997185f7..393f641e68 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -5224,49 +5224,55 @@ FT_DECLARE(char *) ftdm_strndup(const char *str, ftdm_size_t inlen) } #define FTDM_DEBUG_LINE_LEN 255 +#define handle_snprintf_result(buff, written, len, debugstr) \ + if (written >= len) { \ + ftdm_free(debugstr); \ + return NULL; \ + } \ + len -= written; \ + buff += written; + FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *fchan) { - uint8_t j = 0; + char func[255]; + char line[255]; + char states[255]; int written = 0; char *buff = NULL; - uint8_t i = fchan->hindex; - + uint8_t i = 0; int dbglen = ftdm_array_len(fchan->history) * FTDM_DEBUG_LINE_LEN; int len = dbglen; + if (!fchan->history[0].file) { + return ftdm_strdup("-- No state history --\n"); + } + char *debugstr = ftdm_calloc(1, dbglen); if (!debugstr) { return NULL; } buff = debugstr; + written = snprintf(buff, len, "%-30.30s %-30.30s %s", "-- States --", "-- Function --", "-- Location --\n"); + handle_snprintf_result(buff, written, len, debugstr); + for (i = fchan->hindex; i < ftdm_array_len(fchan->history); i++) { if (!fchan->history[i].file) { break; } - written = snprintf(buff, len, "%s -> %s at %s %s:%d\n", - ftdm_channel_state2str(fchan->history[i].last_state), ftdm_channel_state2str(fchan->history[i].state), fchan->history[i].func, - fchan->history[i].file, fchan->history[i].line); - if (written >= len) { - ftdm_free(debugstr); - ftdm_log(FTDM_LOG_ERROR, "Not enough memory to build debug history string\n"); - return NULL; - } - len -= written; - buff += written; + snprintf(states, sizeof(states), "%-5.15s => %-5.15s", ftdm_channel_state2str(fchan->history[i].last_state), ftdm_channel_state2str(fchan->history[i].state)); + snprintf(func, sizeof(func), "[%s]", fchan->history[i].func); + snprintf(line, sizeof(func), "[%s:%d]", fchan->history[i].file, fchan->history[i].line); + written = snprintf(buff, len, "%-30.30s %-30.30s %s\n", states, func, line); + handle_snprintf_result(buff, written, len, debugstr); } - for (j = 0; j < fchan->hindex; j++) { - written = snprintf(buff, len, "%s -> %s at %s %s:%d\n", - ftdm_channel_state2str(fchan->history[i].last_state), ftdm_channel_state2str(fchan->history[i].state), fchan->history[i].func, - fchan->history[i].file, fchan->history[i].line); - if (written >= len) { - ftdm_free(debugstr); - ftdm_log(FTDM_LOG_ERROR, "Not enough memory to build debug history string\n"); - return NULL; - } - len -= written; - buff += written; + for (i = 0; i < fchan->hindex; i++) { + snprintf(states, sizeof(states), "%-5.15s => %-5.15s", ftdm_channel_state2str(fchan->history[i].last_state), ftdm_channel_state2str(fchan->history[i].state)); + snprintf(func, sizeof(func), "[%s]", fchan->history[i].func); + snprintf(line, sizeof(func), "[%s:%d]", fchan->history[i].file, fchan->history[i].line); + written = snprintf(buff, len, "%-30.30s %-30.30s %s\n", states, func, line); + handle_snprintf_result(buff, written, len, debugstr); } debugstr[dbglen-1] = 0; From d9fece6c0e325ee0a5394807395f2b2e2bf68f20 Mon Sep 17 00:00:00 2001 From: Konrad Hammel Date: Thu, 23 Sep 2010 10:09:38 -0400 Subject: [PATCH 3/4] freetdm: ss7 - update to timers to match changes in core timers --- .../ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c | 12 ++++++------ .../ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h | 2 +- .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) 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 19f042bc2e..3ef8db53d1 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 @@ -493,7 +493,7 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /*now go to the RING state */ ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING); - } else if (i > g_ftdm_sngss7_data.min_digits) { + } else if (i >= g_ftdm_sngss7_data.min_digits) { SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, g_ftdm_sngss7_data.min_digits); /*now go to the RING state */ @@ -511,7 +511,7 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) sngss7_info->t35.beat, sngss7_info->t35.callback, &sngss7_info->t35, - &sngss7_info->t35.heartbeat_timer)) { + &sngss7_info->t35.hb_timer_id)) { SS7_ERROR ("Unable to schedule timer, hanging up call!\n"); @@ -536,8 +536,8 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) } /* kill t35 if active */ - if (sngss7_info->t35.heartbeat_timer) { - ftdm_sched_cancel_timer (sngss7_info->t35.sched,&sngss7_info->t35.heartbeat_timer); + if (sngss7_info->t35.hb_timer_id) { + ftdm_sched_cancel_timer (sngss7_info->t35.sched, sngss7_info->t35.hb_timer_id); } SS7_DEBUG_CHAN(ftdmchan, "Sending incoming call from %s to %s to FTDM core\n", @@ -816,8 +816,8 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) } /* if ((ftdmchan->last_state == FTDM_CHANNEL_STATE_RESTART) */ /* check if t35 is active */ - if (sngss7_info->t35.heartbeat_timer) { - ftdm_sched_cancel_timer (sngss7_info->t35.sched, &sngss7_info->t35.heartbeat_timer); + if (sngss7_info->t35.hb_timer_id) { + ftdm_sched_cancel_timer (sngss7_info->t35.sched, sngss7_info->t35.hb_timer_id); } /* clear all of the call specific data store in the channel structure */ 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 415a897181..850bbf0d1a 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 @@ -316,7 +316,7 @@ typedef struct ftdm_sngss7_data { }ftdm_sngss7_data_t; typedef struct sngss7_timer_data { - ftdm_timer_t *heartbeat_timer; + ftdm_timer_id_t hb_timer_id; int beat; int counter; ftdm_sched_callback_t callback; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c index 5185ffcc62..75b32d6892 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c @@ -64,7 +64,7 @@ void handle_isup_t35(void *userdata) sngss7_set_flag(sngss7_info, FLAG_LOCAL_REL); /* hang up on timer expiry */ - ftdmchan->caller_data.hangup_cause = 102; + ftdmchan->caller_data.hangup_cause = 28; /* end the call */ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); From f37729152d625e24c4a6303be2bad8a8245765c2 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 23 Sep 2010 09:30:08 -0400 Subject: [PATCH 4/4] freetdm: dump uuid of the channel associated session if any --- libs/freetdm/mod_freetdm/mod_freetdm.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 8ec44ef60c..086cc4ae2e 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -3451,7 +3451,10 @@ void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stre const char *chan_type; const char *state; const char *last_state; + const char *uuid = NULL; + char sessionid[255]; float txgain, rxgain; + switch_core_session_t *session = NULL; ftdm_alarm_flag_t alarmflag; ftdm_caller_data_t *caller_data; ftdm_channel_t *ftdmchan; @@ -3461,6 +3464,7 @@ void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stre return; } + strcpy(sessionid, "(none)"); ftdmchan = ftdm_span_get_channel(span, chan_id); span_id = ftdm_span_get_id(span); @@ -3475,6 +3479,16 @@ void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stre ftdm_channel_get_sig_status(ftdmchan, &sigstatus); ftdm_channel_get_alarms(ftdmchan, &alarmflag); + uuid = ftdm_channel_get_uuid(ftdmchan, 0); + if (!zstr(uuid)) { + if (!(session = switch_core_session_locate(uuid))) { + snprintf(sessionid, sizeof(sessionid), "%s (dead)", uuid); + } else { + snprintf(sessionid, sizeof(sessionid), "%s", uuid); + switch_core_session_rwunlock(session); + } + } + stream->write_function(stream, "span_id: %u\n" "chan_id: %u\n" @@ -3494,7 +3508,8 @@ void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stre "aniII: %s\n" "dnis: %s\n" "rdnis: %s\n" - "cause: %s\n\n", + "cause: %s\n" + "session: %s\n\n", span_id, chan_id, phspan_id, @@ -3513,7 +3528,8 @@ void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stre caller_data->aniII, caller_data->dnis.digits, caller_data->rdnis.digits, - switch_channel_cause2str(caller_data->hangup_cause)); + switch_channel_cause2str(caller_data->hangup_cause), + sessionid); } void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream)