Merge remote branch 'smgorig/master'

This commit is contained in:
Moises Silva 2010-09-24 14:15:32 -04:00
commit 55757c4f77
19 changed files with 708 additions and 512 deletions

View File

@ -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)
@ -3660,7 +3676,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 +4010,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);
}
@ -4074,7 +4095,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load)
ftdm_global_set_logger(ftdm_logger);
ftdm_cpu_monitor_disable();
ftdm_global_set_mod_directory(SWITCH_GLOBAL_dirs.mod_dir);
ftdm_global_set_config_directory(SWITCH_GLOBAL_dirs.conf_dir);
if (ftdm_global_init() != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error loading FreeTDM\n");

View File

@ -37,6 +37,27 @@
#include "private/ftdm_core.h"
#ifndef FTDM_MOD_DIR
#define FTDM_MOD_DIR "."
#endif
#define FTDM_MAX_CONF_DIR 512
static char g_ftdm_config_dir[FTDM_MAX_CONF_DIR] = FTDM_CONFIG_DIR;
static char g_ftdm_mod_dir[FTDM_MAX_CONF_DIR] = FTDM_MOD_DIR;
FT_DECLARE(void) ftdm_global_set_mod_directory(const char *path)
{
snprintf(g_ftdm_mod_dir, sizeof(g_ftdm_mod_dir), "%s", path);
ftdm_log(FTDM_LOG_DEBUG, "New mod directory: %s\n", g_ftdm_mod_dir);
}
FT_DECLARE(void) ftdm_global_set_config_directory(const char *path)
{
snprintf(g_ftdm_config_dir, sizeof(g_ftdm_config_dir), "%s", path);
ftdm_log(FTDM_LOG_DEBUG, "New config directory: %s\n", g_ftdm_config_dir);
}
int ftdm_config_open_file(ftdm_config_t *cfg, const char *file_path)
{
FILE *f;
@ -46,7 +67,7 @@ int ftdm_config_open_file(ftdm_config_t *cfg, const char *file_path)
if (file_path[0] == '/') {
path = file_path;
} else {
snprintf(path_buf, sizeof(path_buf), "%s%s%s", FTDM_CONFIG_DIR, FTDM_PATH_SEPARATOR, file_path);
snprintf(path_buf, sizeof(path_buf), "%s%s%s", g_ftdm_config_dir, FTDM_PATH_SEPARATOR, file_path);
path = path_buf;
}
@ -64,7 +85,7 @@ int ftdm_config_open_file(ftdm_config_t *cfg, const char *file_path)
int last = -1;
char *var, *val;
snprintf(path_buf, sizeof(path_buf), "%s%sfreetdm.conf", FTDM_CONFIG_DIR, FTDM_PATH_SEPARATOR);
snprintf(path_buf, sizeof(path_buf), "%s%sfreetdm.conf", g_ftdm_config_dir, FTDM_PATH_SEPARATOR);
path = path_buf;
if ((f = fopen(path, "r")) == 0) {
@ -268,13 +289,24 @@ FT_DECLARE(ftdm_status_t) ftdm_conf_node_create(const char *name, ftdm_conf_node
if (parent) {
/* store who my parent is */
newnode->parent = parent;
/* save any siblings */
sibling = parent->child;
/* as a newborn I am first */
parent->child = newnode;
if (sibling) {
/* store a pointer to my next sibling */
newnode->next = sibling;
/* arrange them in FIFO order (newnode should be last) */
if (!parent->child) {
/* we're the first node being added */
parent->child = newnode;
} else {
if (!parent->last) {
/* we're the second node being added */
parent->last = newnode;
parent->child->next = newnode;
newnode->prev = parent->child;
} else {
/* we're the third or Nth node to be added */
sibling = parent->last;
sibling->next = newnode;
parent->last = newnode;
newnode->prev = sibling;
}
}
}
@ -318,6 +350,26 @@ FT_DECLARE(ftdm_status_t) ftdm_conf_node_destroy(ftdm_conf_node_t *node)
return FTDM_SUCCESS;
}
FT_DECLARE(char *) ftdm_build_dso_path(const char *name, char *path, ftdm_size_t len)
{
#ifdef WIN32
const char *ext = ".dll";
//const char *EXT = ".DLL";
#elif defined (MACOSX) || defined (DARWIN)
const char *ext = ".dylib";
//const char *EXT = ".DYLIB";
#else
const char *ext = ".so";
//const char *EXT = ".SO";
#endif
if (*name == *FTDM_PATH_SEPARATOR) {
snprintf(path, len, "%s%s", name, ext);
} else {
snprintf(path, len, "%s%s%s%s", g_ftdm_mod_dir, FTDM_PATH_SEPARATOR, name, ext);
}
return path;
}
/* For Emacs:
* Local Variables:
* mode:c

View File

@ -50,6 +50,7 @@
#endif
#include "ftdm_cpu_monitor.h"
#define FORCE_HANGUP_TIMER 3000
#define SPAN_PENDING_CHANS_QUEUE_SIZE 1000
#define SPAN_PENDING_SIGNALS_QUEUE_SIZE 1000
#define FTDM_READ_TRACE_INDEX 0
@ -85,6 +86,7 @@ FT_DECLARE(ftdm_time_t) ftdm_current_time_in_ms(void)
}
typedef struct {
uint8_t enabled;
uint8_t running;
uint8_t alarm;
uint32_t interval;
@ -102,6 +104,7 @@ static struct {
ftdm_mutex_t *mutex;
ftdm_mutex_t *span_mutex;
ftdm_mutex_t *group_mutex;
ftdm_sched_t *timingsched;
uint32_t span_index;
uint32_t group_index;
uint32_t running;
@ -110,8 +113,6 @@ static struct {
cpu_monitor_t cpu_monitor;
} globals;
static uint8_t ftdm_cpu_monitor_disabled = 0;
enum ftdm_enum_cpu_alarm_action_flags
{
FTDM_CPU_ALARM_ACTION_WARN = (1 << 0),
@ -1291,6 +1292,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);
@ -2002,6 +2013,9 @@ static ftdm_status_t call_hangup(ftdm_channel_t *chan, const char *file, const c
/* make user's life easier, and just ignore double hangup requests */
return FTDM_SUCCESS;
}
if (chan->hangup_timer) {
ftdm_sched_cancel_timer(globals.timingsched, chan->hangup_timer);
}
ftdm_channel_set_state(file, func, line, chan, FTDM_CHANNEL_STATE_HANGUP, 1);
} else {
/* the signaling stack did not touch the state,
@ -2283,6 +2297,9 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
close_dtmf_debug(ftdmchan);
#endif
ftdm_channel_clear_vars(ftdmchan);
if (ftdmchan->hangup_timer) {
ftdm_sched_cancel_timer(globals.timingsched, ftdmchan->hangup_timer);
}
ftdmchan->init_state = FTDM_CHANNEL_STATE_DOWN;
ftdmchan->state = FTDM_CHANNEL_STATE_DOWN;
@ -3671,6 +3688,102 @@ static struct {
ftdm_io_interface_t *pika_interface;
} interfaces;
static void print_channels_by_state(ftdm_stream_handle_t *stream, ftdm_channel_state_t state, int not, int *count)
{
ftdm_hash_iterator_t *i = NULL;
ftdm_span_t *span;
ftdm_channel_t *fchan = NULL;
ftdm_iterator_t *citer = NULL;
ftdm_iterator_t *curr = NULL;
const void *key = NULL;
void *val = NULL;
*count = 0;
ftdm_mutex_lock(globals.mutex);
for (i = hashtable_first(globals.span_hash); i; i = hashtable_next(i)) {
hashtable_this(i, &key, NULL, &val);
if (!key || !val) {
break;
}
span = val;
citer = ftdm_span_get_chan_iterator(span, NULL);
if (!citer) {
continue;
}
for (curr = citer ; curr; curr = ftdm_iterator_next(curr)) {
fchan = ftdm_iterator_current(curr);
if (not && (fchan->state != state)) {
stream->write_function(stream, "[s%dc%d][%d:%d] in state %s\n",
fchan->span_id, fchan->chan_id,
fchan->physical_span_id, fchan->physical_chan_id, ftdm_channel_state2str(fchan->state));
(*count)++;
} else if (!not && (fchan->state == state)) {
stream->write_function(stream, "[s%dc%d][%d:%d] in state %s\n",
fchan->span_id, fchan->chan_id,
fchan->physical_span_id, fchan->physical_chan_id, ftdm_channel_state2str(fchan->state));
(*count)++;
}
}
ftdm_iterator_free(citer);
}
ftdm_mutex_unlock(globals.mutex);
}
static char *handle_core_command(const char *cmd)
{
char *mycmd = NULL;
int argc = 0;
int count = 0;
int not = 0;
char *argv[10] = { 0 };
char *state = NULL;
ftdm_channel_state_t i = FTDM_CHANNEL_STATE_INVALID;
ftdm_stream_handle_t stream = { 0 };
FTDM_STANDARD_STREAM(stream);
if (cmd) {
mycmd = ftdm_strdup(cmd);
argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
} else {
stream.write_function(&stream, "invalid core command\n");
goto done;
}
if (!strcasecmp(argv[0], "state")) {
if (argc < 2) {
stream.write_function(&stream, "core state command requires an argument\n");
goto done;
}
state = argv[1];
if (argv[1][0] == '!') {
not = 1;
state++;
}
for (i = FTDM_CHANNEL_STATE_DOWN; i < FTDM_CHANNEL_STATE_INVALID; i++) {
if (!strcasecmp(state, ftdm_channel_state2str(i))) {
break;
}
}
if (i == FTDM_CHANNEL_STATE_INVALID) {
stream.write_function(&stream, "invalid state %s\n", state);
goto done;
}
print_channels_by_state(&stream, i, not, &count);
stream.write_function(&stream, "\nTotal channels %s %s: %d\n", not ? "not in state" : "in state", ftdm_channel_state2str(i), count);
} else {
stream.write_function(&stream, "invalid core command %s\n", argv[0]);
}
done:
ftdm_safe_free(mycmd);
return stream.data;
}
FT_DECLARE(char *) ftdm_api_execute(const char *cmd)
{
ftdm_io_interface_t *fio = NULL;
@ -3686,6 +3799,10 @@ FT_DECLARE(char *) ftdm_api_execute(const char *cmd)
type = dup;
if (!strcasecmp(type, "core")) {
return handle_core_command(cmd);
}
ftdm_mutex_lock(globals.mutex);
if (!(fio = (ftdm_io_interface_t *) hashtable_search(globals.interface_hash, (void *)type))) {
ftdm_load_module_assume(type);
@ -3986,7 +4103,14 @@ static ftdm_status_t load_config(void)
ftdm_log(FTDM_LOG_ERROR, "unknown span variable '%s'\n", var);
}
} else if (!strncasecmp(cfg.category, "general", 7)) {
if (!strncasecmp(var, "cpu_monitoring_interval", sizeof("cpu_monitoring_interval")-1)) {
if (!strncasecmp(var, "cpu_monitor", sizeof("cpu_monitor")-1)) {
if (!strncasecmp(val, "yes", 3)) {
globals.cpu_monitor.enabled = 1;
if (!globals.cpu_monitor.alarm_action_flags) {
globals.cpu_monitor.alarm_action_flags |= FTDM_CPU_ALARM_ACTION_WARN;
}
}
} else if (!strncasecmp(var, "cpu_monitoring_interval", sizeof("cpu_monitoring_interval")-1)) {
if (atoi(val) > 0) {
globals.cpu_monitor.interval = atoi(val);
} else {
@ -4065,27 +4189,6 @@ static ftdm_status_t process_module_config(ftdm_io_interface_t *fio)
return FTDM_SUCCESS;
}
FT_DECLARE(char *) ftdm_build_dso_path(const char *name, char *path, ftdm_size_t len)
{
#ifdef WIN32
const char *ext = ".dll";
//const char *EXT = ".DLL";
#define FTDM_MOD_DIR "." //todo
#elif defined (MACOSX) || defined (DARWIN)
const char *ext = ".dylib";
//const char *EXT = ".DYLIB";
#else
const char *ext = ".so";
//const char *EXT = ".SO";
#endif
if (*name == *FTDM_PATH_SEPARATOR) {
snprintf(path, len, "%s%s", name, ext);
} else {
snprintf(path, len, "%s%s%s%s", FTDM_MOD_DIR, FTDM_PATH_SEPARATOR, name, ext);
}
return path;
}
FT_DECLARE(ftdm_status_t) ftdm_global_add_io_interface(ftdm_io_interface_t *interface1)
{
ftdm_status_t ret = FTDM_SUCCESS;
@ -4601,6 +4704,21 @@ FT_DECLARE(ftdm_status_t) ftdm_span_trigger_signals(const ftdm_span_t *span)
return FTDM_SUCCESS;
}
static void execute_safety_hangup(void *data)
{
ftdm_channel_t *fchan = data;
ftdm_channel_lock(fchan);
fchan->hangup_timer = 0;
if (fchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan(fchan, FTDM_LOG_CRIT, "Forcing hangup since the user did not confirmed our hangup after %dms\n", FORCE_HANGUP_TIMER);
call_hangup(fchan, __FILE__, __FUNCTION__, __LINE__);
} else {
ftdm_log_chan(fchan, FTDM_LOG_CRIT, "Not performing safety hangup, channel state is %s\n", ftdm_channel_state2str(fchan->state));
}
ftdm_channel_unlock(fchan);
}
FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
{
if (sigmsg->channel) {
@ -4634,6 +4752,11 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user already requested hangup\n");
goto done;
}
if (sigmsg->channel->state == FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Scheduling safety hangup timer\n");
/* if the user does not move us to hangup in 2 seconds, we will do it ourselves */
ftdm_sched_timer(globals.timingsched, "safety-hangup", FORCE_HANGUP_TIMER, execute_safety_hangup, sigmsg->channel, &sigmsg->channel->hangup_timer);
}
break;
default:
@ -4732,12 +4855,6 @@ static void ftdm_cpu_monitor_stop(void)
ftdm_interrupt_destroy(&globals.cpu_monitor.interrupt);
}
FT_DECLARE(void) ftdm_cpu_monitor_disable(void)
{
ftdm_cpu_monitor_disabled = 1;
}
FT_DECLARE(ftdm_status_t) ftdm_global_init(void)
{
memset(&globals, 0, sizeof(globals));
@ -4755,6 +4872,14 @@ FT_DECLARE(ftdm_status_t) ftdm_global_init(void)
ftdm_mutex_create(&globals.span_mutex);
ftdm_mutex_create(&globals.group_mutex);
ftdm_sched_global_init();
if (ftdm_sched_create(&globals.timingsched, "freetdm-master") != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to create master timing schedule context\n");
return FTDM_FAIL;
}
if (ftdm_sched_free_run(globals.timingsched) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to run master timing schedule context\n");
return FTDM_FAIL;
}
globals.running = 1;
return FTDM_SUCCESS;
}
@ -4771,8 +4896,9 @@ FT_DECLARE(ftdm_status_t) ftdm_global_configuration(void)
ftdm_log(FTDM_LOG_NOTICE, "Modules configured: %d \n", modcount);
globals.cpu_monitor.enabled = 0;
globals.cpu_monitor.interval = 1000;
globals.cpu_monitor.alarm_action_flags = FTDM_CPU_ALARM_ACTION_WARN | FTDM_CPU_ALARM_ACTION_REJECT;
globals.cpu_monitor.alarm_action_flags = 0;
globals.cpu_monitor.set_alarm_threshold = 80;
globals.cpu_monitor.reset_alarm_threshold = 70;
@ -4782,7 +4908,12 @@ FT_DECLARE(ftdm_status_t) ftdm_global_configuration(void)
return FTDM_FAIL;
}
if (!ftdm_cpu_monitor_disabled) {
if (globals.cpu_monitor.enabled) {
ftdm_log(FTDM_LOG_INFO, "CPU Monitor is running interval:%d lo-thres:%d hi-thres:%d\n",
globals.cpu_monitor.interval,
globals.cpu_monitor.set_alarm_threshold,
globals.cpu_monitor.reset_alarm_threshold);
if (ftdm_cpu_monitor_start() != FTDM_SUCCESS) {
return FTDM_FAIL;
}
@ -4807,6 +4938,8 @@ FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void)
globals.running = 0;
ftdm_sched_destroy(&globals.timingsched);
ftdm_cpu_monitor_stop();
globals.span_index = 0;
@ -5175,6 +5308,42 @@ FT_DECLARE(char *) ftdm_strndup(const char *str, ftdm_size_t inlen)
return new;
}
FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *fchan)
{
char func[255];
char line[255];
char states[255];
uint8_t i = 0;
ftdm_stream_handle_t stream = { 0 };
FTDM_STANDARD_STREAM(stream);
if (!fchan->history[0].file) {
stream.write_function(&stream, "-- No state history --\n");
return stream.data;
}
stream.write_function(&stream, "%-30.30s %-30.30s %s", "-- States --", "-- Function --", "-- Location --\n");
for (i = fchan->hindex; i < ftdm_array_len(fchan->history); i++) {
if (!fchan->history[i].file) {
break;
}
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);
stream.write_function(&stream, "%-30.30s %-30.30s %s\n", states, func, line);
}
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);
stream.write_function(&stream, "%-30.30s %-30.30s %s\n", states, func, line);
}
return stream.data;
}
/* For Emacs:
* Local Variables:

View File

@ -34,6 +34,8 @@
#include "private/ftdm_core.h"
typedef struct ftdm_timer ftdm_timer_t;
static struct {
ftdm_sched_t *freeruns;
ftdm_mutex_t *mutex;
@ -42,6 +44,7 @@ static struct {
struct ftdm_sched {
char name[80];
ftdm_timer_id_t currid;
ftdm_mutex_t *mutex;
ftdm_timer_t *timers;
int freerun;
@ -51,6 +54,7 @@ struct ftdm_sched {
struct ftdm_timer {
char name[80];
ftdm_timer_id_t id;
#ifdef __linux__
struct timeval time;
#endif
@ -191,6 +195,7 @@ FT_DECLARE(ftdm_status_t) ftdm_sched_create(ftdm_sched_t **sched, const char *na
}
ftdm_set_string(newsched->name, name);
newsched->currid = 1;
*sched = newsched;
ftdm_log(FTDM_LOG_DEBUG, "Created schedule %s\n", name);
@ -219,12 +224,13 @@ FT_DECLARE(ftdm_status_t) ftdm_sched_run(ftdm_sched_t *sched)
int rc = -1;
void *data;
struct timeval now;
ftdm_assert_return(sched != NULL, FTDM_EINVAL, "sched is null!\n");
ftdm_mutex_lock(sched->mutex);
tryagain:
ftdm_mutex_lock(sched->mutex);
rc = gettimeofday(&now, NULL);
if (rc == -1) {
ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve time of day\n");
@ -257,11 +263,16 @@ tryagain:
runtimer->prev->next = runtimer->next;
}
runtimer->id = 0;
ftdm_safe_free(runtimer);
/* avoid deadlocks by releasing the sched lock before triggering callbacks */
ftdm_mutex_unlock(sched->mutex);
callback(data);
/* after calling a callback we must start the scanning again since the
* callback may have added or cancelled timers to the linked list */
* callback or some other thread may have added or cancelled timers to
* the linked list */
goto tryagain;
}
}
@ -283,7 +294,7 @@ done:
}
FT_DECLARE(ftdm_status_t) ftdm_sched_timer(ftdm_sched_t *sched, const char *name,
int ms, ftdm_sched_callback_t callback, void *data, ftdm_timer_t **timer)
int ms, ftdm_sched_callback_t callback, void *data, ftdm_timer_id_t *timerid)
{
ftdm_status_t status = FTDM_FAIL;
#ifdef __linux__
@ -296,8 +307,8 @@ FT_DECLARE(ftdm_status_t) ftdm_sched_timer(ftdm_sched_t *sched, const char *name
ftdm_assert_return(callback != NULL, FTDM_EINVAL, "sched callback is null!\n");
ftdm_assert_return(ms > 0, FTDM_EINVAL, "milliseconds must be bigger than 0!\n");
if (timer) {
*timer = NULL;
if (timerid) {
*timerid = 0;
}
rc = gettimeofday(&now, NULL);
@ -312,6 +323,15 @@ FT_DECLARE(ftdm_status_t) ftdm_sched_timer(ftdm_sched_t *sched, const char *name
if (!newtimer) {
goto done;
}
newtimer->id = sched->currid;
sched->currid++;
if (!sched->currid) {
ftdm_log(FTDM_LOG_NOTICE, "Timer id wrap around for sched %s\n", sched->name);
/* we do not want currid to be zero since is an invalid id
* TODO: check that currid does not exists already in the context, it'd be insane
* though, having a timer to live all that time */
sched->currid++;
}
ftdm_set_string(newtimer->name, name);
newtimer->callback = callback;
@ -332,9 +352,10 @@ FT_DECLARE(ftdm_status_t) ftdm_sched_timer(ftdm_sched_t *sched, const char *name
sched->timers = newtimer;
}
if (timer) {
*timer = newtimer;
if (timerid) {
*timerid = newtimer->id;
}
status = FTDM_SUCCESS;
done:
@ -418,53 +439,37 @@ done:
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_sched_cancel_timer(ftdm_sched_t *sched, ftdm_timer_t **intimer)
FT_DECLARE(ftdm_status_t) ftdm_sched_cancel_timer(ftdm_sched_t *sched, ftdm_timer_id_t timerid)
{
ftdm_status_t status = FTDM_FAIL;
ftdm_timer_t *timer;
ftdm_assert_return(sched != NULL, FTDM_EINVAL, "sched is null!\n");
ftdm_assert_return(intimer != NULL, FTDM_EINVAL, "timer is null!\n");
ftdm_assert_return(*intimer != NULL, FTDM_EINVAL, "timer is null!\n");
if (!timerid) {
return FTDM_SUCCESS;
}
ftdm_mutex_lock(sched->mutex);
/* special case where the cancelled timer is the head */
if (*intimer == sched->timers) {
timer = *intimer;
/* the timer next is the new head (even if that means the new head will be NULL)*/
sched->timers = timer->next;
/* if there is a new head, clean its prev member */
if (sched->timers) {
sched->timers->prev = NULL;
}
/* free the old head */
ftdm_safe_free(timer);
status = FTDM_SUCCESS;
*intimer = NULL;
goto done;
}
/* look for the timer and destroy it (we know now that is not head, se we start at the next member after head) */
for (timer = sched->timers->next; timer; timer = timer->next) {
if (timer == *intimer) {
/* look for the timer and destroy it */
for (timer = sched->timers; timer; timer = timer->next) {
if (timer->id == timerid) {
if (timer == sched->timers) {
/* it's the head timer, put a new head */
sched->timers = timer->next;
}
if (timer->prev) {
timer->prev->next = timer->next;
}
if (timer->next) {
timer->next->prev = timer->prev;
}
ftdm_log(FTDM_LOG_DEBUG, "cancelled timer %s\n", timer->name);
ftdm_safe_free(timer);
status = FTDM_SUCCESS;
*intimer = NULL;
break;
}
}
done:
if (status == FTDM_FAIL) {
ftdm_log(FTDM_LOG_ERROR, "Could not find timer %s to cancel it\n", (*intimer)->name);
}
ftdm_mutex_unlock(sched->mutex);

View File

@ -156,7 +156,7 @@ typedef struct sngisdn_chan_data {
uint8_t globalFlg;
sngisdn_glare_data_t glare;
ftdm_timer_t *timers[SNGISDN_NUM_TIMERS];
ftdm_timer_id_t timers[SNGISDN_NUM_TIMERS];
} sngisdn_chan_data_t;
/* Span specific data */

View File

@ -611,6 +611,7 @@ ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.hdr.response.selector=0;
cfg.t.cfg.s.inDLSAP.sapId = signal_data->link_id;
cfg.t.cfg.s.inDLSAP.spId = signal_data->link_id;
cfg.t.cfg.s.inDLSAP.swtch = sng_isdn_stack_switchtype(signal_data->switchtype);

View File

@ -131,14 +131,12 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
}
if (conEvnt->facilityStr.eh.pres) {
if (signal_data->facility == SNGISDN_OPT_TRUE && conEvnt->facilityStr.eh.pres) {
/* Verify whether the Caller Name will come in a subsequent FACILITY message */
uint16_t ret_val;
uint8_t facility_str[255];
char retrieved_str[255];
memcpy(facility_str, (uint8_t*)&conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len);
ret_val = sng_isdn_retrieve_facility_caller_name(facility_str, conEvnt->facilityStr.facilityStr.len, retrieved_str);
ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str);
/*
return values for "sng_isdn_retrieve_facility_information_following":
If there will be no information following, or fails to decode IE, returns -1
@ -151,7 +149,8 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID);
/* Launch timer in case we never get a FACILITY msg */
if (signal_data->facility_timeout) {
ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout,
sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
}
break;
} else if (ret_val == 0) {
@ -702,14 +701,23 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_GET_CALLERID:
/* Update the caller ID Name */
if (facEvnt->facElmt.facStr.pres) {
uint8_t facility_str[255];
memcpy(facility_str, (uint8_t*)&facEvnt->facElmt.facStr.val, facEvnt->facElmt.facStr.len);
char retrieved_str[255];
if (sng_isdn_retrieve_facility_caller_name(facility_str, facEvnt->facElmt.facStr.len, retrieved_str) != FTDM_SUCCESS) {
/* return values for "sng_isdn_retrieve_facility_information_following":
If there will be no information following, or fails to decode IE, returns -1
If there will be no information following, but current FACILITY IE contains a caller name, returns 0
If there will be information following, returns 1
*/
if (sng_isdn_retrieve_facility_caller_name(&facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len, retrieved_str) == 0) {
strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to retrieve Caller Name from Facility IE\n");
}
/* Cancel facility timeout */
ftdm_sched_cancel_timer(signal_data->sched, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
if (signal_data->facility_timeout) {
/* Cancel facility timeout */
ftdm_sched_cancel_timer(signal_data->sched, sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
}
}
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
@ -884,6 +892,22 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
break;
}
break;
case 9: /* Remote switch is in "Incoming call proceeding" state */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_GET_CALLERID:
/* Do nothing */
break;
case FTDM_CHANNEL_STATE_UP:
/* Remote switch missed our CONNECT message, re-send */
ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "delayed_connect", 1, sngisdn_delayed_connect, (void*) sngisdn_info, NULL);
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
}
break;
case 10: /* Remote switch is in active state */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_UP:
@ -899,17 +923,6 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
break;
}
break;
case 9:
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
/* Do nothing */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
}
break;
case 22:
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_UP:

View File

@ -1506,6 +1506,10 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c
sngss7_span_data_t *sngss7_span;
int byte = 0;
int bit = 0;
ftdm_sigmsg_t sigev;
memset (&sigev, 0, sizeof (sigev));
if (range > 31) {
stream->write_function(stream, "Invalid range value %d", range);
@ -1531,6 +1535,14 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c
/* throw the grp maint. block flag */
sngss7_set_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX);
/* bring the sig status down */
sigev.chan_id = ftdmchan->chan_id;
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* if this is the first channel in the range */
if (ftdmchan->physical_chan_id == chan) {
/* attach the cgb information */
@ -1575,6 +1587,10 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
sngss7_span_data_t *sngss7_span;
int byte = 0;
int bit = 0;
ftdm_sigmsg_t sigev;
memset (&sigev, 0, sizeof (sigev));
if (range > 31) {
stream->write_function(stream, "Invalid range value %d", range);
@ -1600,6 +1616,14 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
/* throw the grp maint. block flag */
sngss7_clear_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX);
/* bring the sig status up */
sigev.chan_id = ftdmchan->chan_id;
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* if this is the first channel in the range */
if (ftdmchan->physical_chan_id == chan) {
/* attach the cgb information */

View File

@ -496,6 +496,12 @@ void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
/* initalize the msg variable to NULLs */
memset(&msg[0], '\0', sizeof(&msg));
/* if the event is REMOTE/LOCAL we don't need to print these */
if ((sta->t.usta.alarm.event == LSI_EVENT_REMOTE) ||
(sta->t.usta.alarm.event == LSI_EVENT_LOCAL)) {
return;
}
/* point p to the first spot in msg */
p = &msg[0];
@ -728,6 +734,8 @@ void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
DECODE_LSI_EVENT(sta->t.usta.alarm.event),
DECODE_LSI_CAUSE(sta->t.usta.alarm.cause));
return;
} /* handle_isup_alarm */
/******************************************************************************/

View File

@ -454,9 +454,9 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
/******************************************************************************/
static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
{
ftdm_sigmsg_t sigev;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
int i = 0;
ftdm_sigmsg_t sigev;
memset (&sigev, 0, sizeof (sigev));
@ -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",
@ -788,14 +788,24 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
!(sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX)) &&
!(sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX))) {
/* check if the sig status is down, and bring it up if it isn't */
if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
SS7_DEBUG_CHAN(ftdmchan,"All reset flags cleared %s\n", "");
/* all flags are down so we can bring up the sig status */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
ftdm_span_send_signal (ftdmchan->span, &sigev);
}
/* now check if there is an active block */
if (!(sngss7_test_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) &&
!(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) &&
!(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) &&
!(sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) &&
!(sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) &&
!(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) &&
!(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) {
/* check if the sig status is down, and bring it up if it isn't */
if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
SS7_DEBUG_CHAN(ftdmchan,"All reset flags cleared %s\n", "");
/* all flags are down so we can bring up the sig status */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
ftdm_span_send_signal (ftdmchan->span, &sigev);
} /* if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) */
} /* if !blocked */
} else {
SS7_DEBUG_CHAN(ftdmchan,"Reset flags present (0x%X)\n", sngss7_info->flags);
@ -806,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 */
@ -993,6 +1003,11 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_BLOCK_RX)) {
SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_RX flag %s\n", "");
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a BLA */
ft_to_sngss7_bla (ftdmchan);
@ -1006,6 +1021,11 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* clear the unblock flag */
sngss7_clear_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX);
/* bring the sig status up */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a uba */
ft_to_sngss7_uba (ftdmchan);
@ -1017,6 +1037,11 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_BLOCK_TX)) {
SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_TX flag %s\n", "");
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a blo */
ft_to_sngss7_blo (ftdmchan);
@ -1030,6 +1055,11 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* clear the unblock flag */
sngss7_clear_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX);
/* bring the sig status up */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a ubl */
ft_to_sngss7_ubl (ftdmchan);
@ -1403,6 +1433,9 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_ss7_span_config)
static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init)
{
/*this function is called by the FT-core to load the signaling module */
uint32_t major = 0;
uint32_t minor = 0;
uint32_t build = 0;
ftdm_log (FTDM_LOG_INFO, "Loading ftmod_sangoma_ss7...\n");
@ -1452,6 +1485,10 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init)
/* initalize sng_ss7 library */
sng_isup_init (&sng_event);
/* print the version of the library being used */
sng_isup_version(&major, &minor, &build);
SS7_INFO("Loaded LibSng-SS7 %d.%d.%d\n", major, minor, build);
/* crash on assert fail */
ftdm_global_set_crash_policy (FTDM_CRASH_ON_ASSERT);

View File

@ -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;

View File

@ -199,7 +199,8 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
&iam,
0);
SS7_INFO_CHAN(ftdmchan,"Tx IAM clg = \"%s\", cld = \"%s\"\n",
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM clg = \"%s\", cld = \"%s\"\n",
sngss7_info->circuit->cic,
ftdmchan->caller_data.cid_num.digits,
ftdmchan->caller_data.dnis.digits);
@ -250,7 +251,7 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
&acm,
ADDRCMPLT);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx ACM\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ACM\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -274,7 +275,7 @@ void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan)
&anm,
5);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx ANM\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ANM\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -307,7 +308,9 @@ void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan)
sngss7_info->circuit->id,
&rel);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx REL\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx REL cause=%d \n",
sngss7_info->circuit->cic,
ftdmchan->caller_data.hangup_cause );
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -330,7 +333,7 @@ void ft_to_sngss7_rlc (ftdm_channel_t * ftdmchan)
sngss7_info->circuit->id,
&rlc);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx RLC\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RLC\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -351,7 +354,7 @@ void ft_to_sngss7_rsc (ftdm_channel_t * ftdmchan)
SIT_STA_CIRRESREQ,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx RSC\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -372,7 +375,7 @@ void ft_to_sngss7_rsca (ftdm_channel_t * ftdmchan)
SIT_STA_CIRRESRSP,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx RSC-RLC\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC-RLC\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -393,7 +396,7 @@ void ft_to_sngss7_blo (ftdm_channel_t * ftdmchan)
SIT_STA_CIRBLOREQ,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx BLO\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLO\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -414,7 +417,7 @@ void ft_to_sngss7_bla (ftdm_channel_t * ftdmchan)
SIT_STA_CIRBLORSP,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx BLA\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLA\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -436,7 +439,7 @@ ft_to_sngss7_ubl (ftdm_channel_t * ftdmchan)
SIT_STA_CIRUBLREQ,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx UBL\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBL\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -457,7 +460,7 @@ void ft_to_sngss7_uba (ftdm_channel_t * ftdmchan)
SIT_STA_CIRUBLRSP,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx UBA\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBA\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -478,7 +481,7 @@ void ft_to_sngss7_lpa (ftdm_channel_t * ftdmchan)
SIT_STA_LOOPBACKACK,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx LPA\n");
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx LPA\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@ -519,7 +522,8 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
SIT_STA_GRSRSP,
&gra);
SS7_INFO_CHAN(ftdmchan, "Tx GRA (%d:%d)\n",
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx GRA (%d:%d)\n",
sngss7_info->circuit->cic,
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->rx_grs.range));
@ -551,7 +555,8 @@ void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan)
SIT_STA_GRSREQ,
&grs);
SS7_INFO_CHAN(ftdmchan, "Tx GRS (%d:%d)\n",
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx GRS (%d:%d)\n",
sngss7_info->circuit->cic,
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->tx_grs.range));
@ -596,7 +601,8 @@ void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan)
SIT_STA_CGBRSP,
&cgba);
SS7_INFO_CHAN(ftdmchan, "Tx CGBA (%d:%d)\n",
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx CGBA (%d:%d)\n",
sngss7_info->circuit->cic,
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->rx_cgb.range));
@ -644,7 +650,8 @@ void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan)
SIT_STA_CGURSP,
&cgua);
SS7_INFO_CHAN(ftdmchan, "Tx CGUA (%d:%d)\n",
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx CGUA (%d:%d)\n",
sngss7_info->circuit->cic,
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->rx_cgu.range));
@ -693,7 +700,8 @@ void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan)
SIT_STA_CGBREQ,
&cgb);
SS7_INFO_CHAN(ftdmchan, "Tx CGB (%d:%d)\n",
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx CGB (%d:%d)\n",
sngss7_info->circuit->cic,
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->tx_cgb.range));
@ -742,7 +750,8 @@ void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan)
SIT_STA_CGUREQ,
&cgu);
SS7_INFO_CHAN(ftdmchan, "Tx CGU (%d:%d)\n",
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx CGU (%d:%d)\n",
sngss7_info->circuit->cic,
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->tx_cgu.range));

View File

@ -464,7 +464,7 @@ ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan)
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
SS7_ASSERT;
continue;
}
/* lock the channel */
@ -476,61 +476,61 @@ ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan)
if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) {
/* this channel is still resetting...do nothing */
goto GRS_UNLOCK_ALL;
} /* if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */
} else {
/* state change pending */
goto GRS_UNLOCK_ALL;
}
} /* for ( i = circuit; i < (circuit + range + 1); i++) */
} /* if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */
} else {
/* state change pending */
goto GRS_UNLOCK_ALL;
}
} /* for ( i = circuit; i < (circuit + range + 1); i++) */
SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n",
sngss7_span->rx_grs.circuit,
sngss7_span->rx_grs.range);
SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n",
sngss7_span->rx_grs.circuit,
sngss7_span->rx_grs.range);
/* check all the circuits in the range to see if they are done resetting */
for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* check all the circuits in the range to see if they are done resetting */
for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i);
SS7_ASSERT;
}
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i);
SS7_ASSERT;
}
/* throw the GRP reset flag complete flag */
sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
/* throw the GRP reset flag complete flag */
sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
/* move the channel to the down state */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
/* move the channel to the down state */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
/* update the status map if the ckt is in blocked state */
if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) ||
(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) ||
(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
/* update the status map if the ckt is in blocked state */
if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) ||
(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) ||
(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
sngss7_span->rx_grs.status[byte] = (sngss7_span->rx_grs.status[byte] | (1 << bit));
} /* if blocked */
sngss7_span->rx_grs.status[byte] = (sngss7_span->rx_grs.status[byte] | (1 << bit));
} /* if blocked */
/* update the bit and byte counter*/
bit ++;
if (bit == 8) {
byte++;
bit = 0;
}
} /* for ( i = circuit; i < (circuit + range + 1); i++) */
/* update the bit and byte counter*/
bit ++;
if (bit == 8) {
byte++;
bit = 0;
}
} /* for ( i = circuit; i < (circuit + range + 1); i++) */
GRS_UNLOCK_ALL:
for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
SS7_ASSERT;
}
/* unlock the channel */
ftdm_mutex_unlock(ftdmchan->mutex);
for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
continue;
}
/* unlock the channel */
ftdm_mutex_unlock(ftdmchan->mutex);
}
return FTDM_SUCCESS;
}

View File

@ -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);

View File

@ -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 */
@ -1301,6 +1307,12 @@ FT_DECLARE(void) ftdm_global_set_logger(ftdm_logger_t logger);
/*! \brief Set the default logger level */
FT_DECLARE(void) ftdm_global_set_default_logger(int level);
/*! \brief Set the directory to look for modules */
FT_DECLARE(void) ftdm_global_set_mod_directory(const char *path);
/*! \brief Set the directory to look for configs */
FT_DECLARE(void) ftdm_global_set_config_directory(const char *path);
/*! \brief Check if the FTDM library is initialized and running */
FT_DECLARE(ftdm_bool_t) ftdm_running(void);

View File

@ -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;
@ -425,6 +436,7 @@ struct ftdm_channel {
float txgain;
int availability_rate;
void *user_private;
ftdm_timer_id_t hangup_timer;
#ifdef FTDM_DEBUG_DTMF
ftdm_dtmf_debug_t dtmfdbg;
#endif

View File

@ -44,8 +44,8 @@ extern "C" {
#define FTDM_MICROSECONDS_PER_SECOND 1000000
typedef struct ftdm_sched ftdm_sched_t;
typedef struct ftdm_timer ftdm_timer_t;
typedef void (*ftdm_sched_callback_t)(void *data);
typedef uint64_t ftdm_timer_id_t;
/*! \brief Create a new scheduling context */
FT_DECLARE(ftdm_status_t) ftdm_sched_create(ftdm_sched_t **sched, const char *name);
@ -62,18 +62,22 @@ FT_DECLARE(ftdm_status_t) ftdm_sched_free_run(ftdm_sched_t *sched);
* \param name Timer name, typically unique but is not required to be unique, any null terminated string is fine (required)
* \param callback The callback to call upon timer expiration (required)
* \param data Optional data to pass to the callback
* \param timer The timer that was created, it can be NULL if you dont care,
* but you need this if you want to be able to cancel the timer with ftdm_sched_cancel_timer
* \param timer Timer id pointer to store the id of the newly created timer. It can be null
* if you do not need to know the id, but you need this if you want to be able
* to cancel the timer with ftdm_sched_cancel_timer
*/
FT_DECLARE(ftdm_status_t) ftdm_sched_timer(ftdm_sched_t *sched, const char *name,
int ms, ftdm_sched_callback_t callback, void *data, ftdm_timer_t **timer);
int ms, ftdm_sched_callback_t callback, void *data, ftdm_timer_id_t *timer);
/*!
* \brief Cancel the timer
* Note that there is a race between cancelling and triggering a timer.
* By the time you call this function the timer may be about to be triggered.
* This is specially true with timers in free run schedule.
* \param sched The scheduling context (required)
* \param timer The timer to cancel (required)
*/
FT_DECLARE(ftdm_status_t) ftdm_sched_cancel_timer(ftdm_sched_t *sched, ftdm_timer_t **timer);
FT_DECLARE(ftdm_status_t) ftdm_sched_cancel_timer(ftdm_sched_t *sched, ftdm_timer_id_t timer);
/*! \brief Destroy the context and all of the scheduled timers in it */
FT_DECLARE(ftdm_status_t) ftdm_sched_destroy(ftdm_sched_t **sched);

View File

@ -322,9 +322,15 @@ struct ftdm_conf_node {
/* first node child */
struct ftdm_conf_node *child;
/* last node child */
struct ftdm_conf_node *last;
/* next node sibling */
struct ftdm_conf_node *next;
/* prev node sibling */
struct ftdm_conf_node *prev;
/* my parent if any */
struct ftdm_conf_node *parent;
};