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");
if (rply) {
stream->write_function(stream, "%s", rply);
- free(rply);
+ ftdm_free(rply);
} else {
stream->write_function(stream, "-ERR Usage: %s\n", FT_SYNTAX);
}
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);
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:
/*! \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 */
} 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 {
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;