Merge remote branch 'fsorig/master' into nfas

Conflicts:
	libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c
	libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
This commit is contained in:
David Yat Sin committed 2012-09-03 22:34:13 -04:00
commit 3a57b0bed6
1605 files changed
+170690 -121271

No files matched your search

+75
View File
@@ -0,0 +1,75 @@
/*
*
*
*/
#define _BSD_SOURCE
#include "private/ftdm_core.h"
#ifdef HAVE_EXECINFO_H
#include <stdlib.h>
#include <unistd.h>
#include <execinfo.h>
#include <syscall.h>
#define FTDM_BACKTRACE_MAX 50
FT_DECLARE(ftdm_status_t) ftdm_backtrace_walk(void (* callback)(const int tid, const void *addr, const char *symbol, void *priv), void *priv)
{
void *stacktrace[FTDM_BACKTRACE_MAX];
char **symbols = NULL;
size_t size = 0;
pid_t tid = 0;
int si = 0;
if (!callback) {
return FTDM_EINVAL;
}
tid = syscall(SYS_gettid);
size = backtrace(stacktrace, ftdm_array_len(stacktrace));
symbols = backtrace_symbols(stacktrace, size);
for (si = 0; si < size; si++) {
callback(tid, stacktrace[si], symbols[si], priv);
}
free(symbols);
return FTDM_SUCCESS;
}
#else /* !HAVE_EXECINFO_H */
FT_DECLARE(ftdm_status_t) ftdm_backtrace_walk(void (* callback)(const int tid, const void *addr, const char *symbol, void *priv), void *priv)
{
ftdm_log(FTDM_LOG_DEBUG, "Stack traces are not available on this platform!\n");
return FTDM_NOTIMPL;
}
#endif
static void span_backtrace(const int tid, const void *addr, const char *symbol, void *priv)
{
ftdm_span_t *span = priv;
ftdm_log(FTDM_LOG_DEBUG, "[%d][tid:%d] %p -> %s\n",
ftdm_span_get_id(span), tid, addr, symbol);
}
FT_DECLARE(ftdm_status_t) ftdm_backtrace_span(ftdm_span_t *span)
{
return ftdm_backtrace_walk(&span_backtrace, span);
}
static void chan_backtrace(const int tid, const void *addr, const char *symbol, void *priv)
{
ftdm_channel_t *chan = priv;
ftdm_log(FTDM_LOG_DEBUG, "[%d:%d][tid:%d] %p -> %s\n",
ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan), tid, addr, symbol);
}
FT_DECLARE(ftdm_status_t) ftdm_backtrace_chan(ftdm_channel_t *chan)
{
return ftdm_backtrace_walk(&chan_backtrace, chan);
}
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
+91 -32
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -262,9 +262,12 @@ FTDM_STR2ENUM(ftdm_str2ftdm_tonemap, ftdm_tonemap2str, ftdm_tonemap_t, TONEMAP_N
FTDM_ENUM_NAMES(OOB_NAMES, OOB_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_oob_event, ftdm_oob_event2str, ftdm_oob_event_t, OOB_NAMES, FTDM_OOB_INVALID)
FTDM_ENUM_NAMES(TRUNK_TYPE_NAMES, TRUNK_STRINGS)
FTDM_ENUM_NAMES(TRUNK_TYPE_NAMES, TRUNK_TYPE_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_trunk_type, ftdm_trunk_type2str, ftdm_trunk_type_t, TRUNK_TYPE_NAMES, FTDM_TRUNK_NONE)
FTDM_ENUM_NAMES(TRUNK_MODE_NAMES, TRUNK_MODE_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_trunk_mode, ftdm_trunk_mode2str, ftdm_trunk_mode_t, TRUNK_MODE_NAMES, FTDM_TRUNK_MODE_INVALID)
FTDM_ENUM_NAMES(START_TYPE_NAMES, START_TYPE_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_analog_start_type, ftdm_analog_start_type2str, ftdm_analog_start_type_t, START_TYPE_NAMES, FTDM_ANALOG_START_NA)
@@ -757,11 +760,16 @@ FT_DECLARE(ftdm_status_t) ftdm_span_stop(ftdm_span_t *span)
goto done;
}
/* Stop SIG */
status = span->stop(span);
if (FTDM_SUCCESS == status) {
if (status == FTDM_SUCCESS) {
ftdm_clear_flag(span, FTDM_SPAN_STARTED);
}
/* Stop I/O */
if (span->fio && span->fio->span_stop) {
status = span->fio->span_stop(span);
}
done:
ftdm_mutex_unlock(span->mutex);
@@ -816,6 +824,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_create(const char *iotype, const char *name,
ftdm_copy_string(new_span->tone_map[FTDM_TONEMAP_BUSY], "%(500,500,480,620)", FTDM_TONEMAP_LEN);
ftdm_copy_string(new_span->tone_map[FTDM_TONEMAP_ATTN], "%(100,100,1400,2060,2450,2600)", FTDM_TONEMAP_LEN);
new_span->trunk_type = FTDM_TRUNK_NONE;
new_span->trunk_mode = FTDM_TRUNK_MODE_CPE;
new_span->data_type = FTDM_TYPE_SPAN;
ftdm_mutex_lock(globals.span_mutex);
@@ -1994,6 +2003,21 @@ FT_DECLARE(const char *) ftdm_span_get_trunk_type_str(const ftdm_span_t *span)
return ftdm_trunk_type2str(span->trunk_type);
}
FT_DECLARE(void) ftdm_span_set_trunk_mode(ftdm_span_t *span, ftdm_trunk_mode_t mode)
{
span->trunk_mode = mode;
}
FT_DECLARE(ftdm_trunk_mode_t) ftdm_span_get_trunk_mode(const ftdm_span_t *span)
{
return span->trunk_mode;
}
FT_DECLARE(const char *) ftdm_span_get_trunk_mode_str(const ftdm_span_t *span)
{
return ftdm_trunk_mode2str(span->trunk_mode);
}
FT_DECLARE(uint32_t) ftdm_span_get_id(const ftdm_span_t *span)
{
return span->span_id;
@@ -4181,6 +4205,9 @@ FT_DECLARE(ftdm_iterator_t *) ftdm_get_iterator(ftdm_iterator_type_t type, ftdm_
FT_DECLARE(ftdm_iterator_t *) ftdm_span_get_chan_iterator(const ftdm_span_t *span, ftdm_iterator_t *iter)
{
if (!span->chan_count) {
return NULL;
}
if (!(iter = ftdm_get_iterator(FTDM_ITERATOR_CHANS, iter))) {
return NULL;
}
@@ -4624,7 +4651,7 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const
static ftdm_status_t load_config(void)
{
char cfg_name[] = "freetdm.conf";
const char cfg_name[] = "freetdm.conf";
ftdm_config_t cfg;
char *var, *val;
int catno = -1;
@@ -4642,7 +4669,9 @@ static ftdm_status_t load_config(void)
if (!ftdm_config_open_file(&cfg, cfg_name)) {
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "Reading FreeTDM configuration file\n");
ftdm_log(FTDM_LOG_DEBUG, "Reading FreeTDM configuration file\n");
while (ftdm_config_next_pair(&cfg, &var, &val)) {
if (*cfg.category == '#') {
if (cfg.catno != catno) {
@@ -4653,14 +4682,14 @@ static ftdm_status_t load_config(void)
if (cfg.catno != catno) {
char *type = cfg.category + 4;
char *name;
if (*type == ' ') {
type++;
}
ftdm_log(FTDM_LOG_DEBUG, "found config for span\n");
catno = cfg.catno;
if (ftdm_strlen_zero(type)) {
ftdm_log(FTDM_LOG_CRIT, "failure creating span, no type specified.\n");
span = NULL;
@@ -4671,7 +4700,7 @@ static ftdm_status_t load_config(void)
*name++ = '\0';
}
/* Verify is trunk_type was specified for previous span */
/* Verify if trunk_type was specified for previous span */
if (span && span->trunk_type == FTDM_TRUNK_NONE) {
ftdm_log(FTDM_LOG_ERROR, "trunk_type not specified for span %d (%s)\n", span->span_id, span->name);
ret = FTDM_FAIL;
@@ -4698,11 +4727,15 @@ static ftdm_status_t load_config(void)
}
ftdm_log(FTDM_LOG_DEBUG, "span %d [%s]=[%s]\n", span->span_id, var, val);
if (!strcasecmp(var, "trunk_type")) {
ftdm_trunk_type_t trtype = ftdm_str2ftdm_trunk_type(val);
ftdm_span_set_trunk_type(span, trtype);
ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s'\n", ftdm_trunk_type2str(trtype));
ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s'\n", ftdm_trunk_type2str(trtype));
} else if (!strcasecmp(var, "trunk_mode")) {
ftdm_trunk_mode_t trmode = ftdm_str2ftdm_trunk_mode(val);
ftdm_span_set_trunk_mode(span, trmode);
ftdm_log(FTDM_LOG_DEBUG, "setting trunk mode to '%s'\n", ftdm_trunk_mode2str(trmode));
} else if (!strcasecmp(var, "name")) {
if (!strcasecmp(val, "undef")) {
chan_config.name[0] = '\0';
@@ -4719,16 +4752,17 @@ static ftdm_status_t load_config(void)
if (span->trunk_type == FTDM_TRUNK_FXS || span->trunk_type == FTDM_TRUNK_FXO || span->trunk_type == FTDM_TRUNK_EM) {
if ((tmp = ftdm_str2ftdm_analog_start_type(val)) != FTDM_ANALOG_START_NA) {
span->start_type = tmp;
ftdm_log(FTDM_LOG_DEBUG, "changing start type to '%s'\n", ftdm_analog_start_type2str(span->start_type));
ftdm_log(FTDM_LOG_DEBUG, "changing start type to '%s'\n", ftdm_analog_start_type2str(span->start_type));
}
} else {
ftdm_log(FTDM_LOG_ERROR, "This option is only valid on analog trunks!\n");
}
} else if (!strcasecmp(var, "fxo-channel")) {
if (span->trunk_type == FTDM_TRUNK_NONE) {
span->trunk_type = FTDM_TRUNK_FXO;
ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s)\n", ftdm_trunk_type2str(span->trunk_type),
ftdm_analog_start_type2str(span->start_type));
span->trunk_type = FTDM_TRUNK_FXO;
span->trunk_mode = FTDM_TRUNK_MODE_CPE;
ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s), mode(%s)\n", ftdm_trunk_type2str(span->trunk_type),
ftdm_analog_start_type2str(span->start_type), ftdm_trunk_mode2str(span->trunk_mode));
}
if (span->trunk_type == FTDM_TRUNK_FXO) {
unsigned chans_configured = 0;
@@ -4737,13 +4771,14 @@ static ftdm_status_t load_config(void)
configured += chans_configured;
}
} else {
ftdm_log(FTDM_LOG_WARNING, "Cannot add FXO channels to an FXS trunk!\n");
ftdm_log(FTDM_LOG_WARNING, "Cannot add FXO channels to a %s trunk!\n", ftdm_trunk_type2str(span->trunk_type));
}
} else if (!strcasecmp(var, "fxs-channel")) {
if (span->trunk_type == FTDM_TRUNK_NONE) {
span->trunk_type = FTDM_TRUNK_FXS;
ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s)\n", ftdm_trunk_type2str(span->trunk_type),
ftdm_analog_start_type2str(span->start_type));
span->trunk_mode = FTDM_TRUNK_MODE_NET;
ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s), mode(%s)\n", ftdm_trunk_type2str(span->trunk_type),
ftdm_analog_start_type2str(span->start_type), ftdm_trunk_mode2str(span->trunk_mode));
}
if (span->trunk_type == FTDM_TRUNK_FXS) {
unsigned chans_configured = 0;
@@ -4752,13 +4787,14 @@ static ftdm_status_t load_config(void)
configured += chans_configured;
}
} else {
ftdm_log(FTDM_LOG_WARNING, "Cannot add FXS channels to an FXO trunk!\n");
ftdm_log(FTDM_LOG_WARNING, "Cannot add FXS channels to a %s trunk!\n", ftdm_trunk_type2str(span->trunk_type));
}
} else if (!strcasecmp(var, "em-channel")) {
if (span->trunk_type == FTDM_TRUNK_NONE) {
span->trunk_type = FTDM_TRUNK_EM;
ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s)\n", ftdm_trunk_type2str(span->trunk_type),
ftdm_analog_start_type2str(span->start_type));
span->trunk_mode = FTDM_TRUNK_MODE_CPE;
ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s), mode(%s)\n", ftdm_trunk_type2str(span->trunk_type),
ftdm_analog_start_type2str(span->start_type), ftdm_trunk_mode2str(span->trunk_mode));
}
if (span->trunk_type == FTDM_TRUNK_EM) {
unsigned chans_configured = 0;
@@ -4767,19 +4803,33 @@ static ftdm_status_t load_config(void)
configured += chans_configured;
}
} else {
ftdm_log(FTDM_LOG_WARNING, "Cannot add EM channels to a non-EM trunk!\n");
ftdm_log(FTDM_LOG_WARNING, "Cannot add EM channels to a %s trunk!\n", ftdm_trunk_type2str(span->trunk_type));
}
} else if (!strcasecmp(var, "b-channel")) {
unsigned chans_configured = 0;
chan_config.type = FTDM_CHAN_TYPE_B;
if (ftdm_configure_span_channels(span, val, &chan_config, &chans_configured) == FTDM_SUCCESS) {
configured += chans_configured;
if (span->trunk_type == FTDM_TRUNK_NONE) {
ftdm_log(FTDM_LOG_ERROR, "No trunk type specified in configuration file\n");
break;
}
if (FTDM_SPAN_IS_DIGITAL(span)) {
unsigned chans_configured = 0;
chan_config.type = FTDM_CHAN_TYPE_B;
if (ftdm_configure_span_channels(span, val, &chan_config, &chans_configured) == FTDM_SUCCESS) {
configured += chans_configured;
}
} else {
ftdm_log(FTDM_LOG_WARNING, "Cannot add B channels to a %s trunk!\n", ftdm_trunk_type2str(span->trunk_type));
}
} else if (!strcasecmp(var, "d-channel")) {
if (d) {
ftdm_log(FTDM_LOG_WARNING, "ignoring extra d-channel\n");
} else {
if (span->trunk_type == FTDM_TRUNK_NONE) {
ftdm_log(FTDM_LOG_ERROR, "No trunk type specified in configuration file\n");
break;
}
if (FTDM_SPAN_IS_DIGITAL(span)) {
unsigned chans_configured = 0;
if (d) {
ftdm_log(FTDM_LOG_WARNING, "ignoring extra d-channel\n");
continue;
}
if (!strncasecmp(val, "lapd:", 5)) {
chan_config.type = FTDM_CHAN_TYPE_DQ931;
val += 5;
@@ -4790,11 +4840,12 @@ static ftdm_status_t load_config(void)
configured += chans_configured;
}
d++;
} else {
ftdm_log(FTDM_LOG_WARNING, "Cannot add D channels to a %s trunk!\n", ftdm_trunk_type2str(span->trunk_type));
}
} else if (!strcasecmp(var, "cas-channel")) {
unsigned chans_configured = 0;
chan_config.type = FTDM_CHAN_TYPE_CAS;
if (ftdm_configure_span_channels(span, val, &chan_config, &chans_configured) == FTDM_SUCCESS) {
configured += chans_configured;
}
@@ -4916,7 +4967,7 @@ done:
if (!configured) {
ret = FTDM_FAIL;
}
return ret;
}
@@ -5263,6 +5314,14 @@ FT_DECLARE(ftdm_status_t) ftdm_span_start(ftdm_span_t *span)
goto done;
}
/* Start I/O */
if (span->fio && span->fio->span_start) {
status = span->fio->span_start(span);
if (status != FTDM_SUCCESS)
goto done;
}
/* Start SIG */
status = ftdm_report_initial_channels_alarms(span);
if (status != FTDM_SUCCESS) {
goto done;
@@ -5661,7 +5720,7 @@ static void *ftdm_cpu_monitor_run(ftdm_thread_t *me, void *obj)
static ftdm_status_t ftdm_cpu_monitor_start(void)
{
if (ftdm_interrupt_create(&globals.cpu_monitor.interrupt, FTDM_INVALID_SOCKET) != FTDM_SUCCESS) {
if (ftdm_interrupt_create(&globals.cpu_monitor.interrupt, FTDM_INVALID_SOCKET, FTDM_NO_FLAGS) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to create CPU monitor interrupt\n");
return FTDM_FAIL;
}
+1 -1
View File
@@ -98,7 +98,7 @@ static ftdm_status_t ftdm_std_queue_create(ftdm_queue_t **outqueue, ftdm_size_t
goto failed;
}
if (ftdm_interrupt_create(&queue->interrupt, FTDM_INVALID_SOCKET) != FTDM_SUCCESS) {
if (ftdm_interrupt_create(&queue->interrupt, FTDM_INVALID_SOCKET, FTDM_NO_FLAGS) != FTDM_SUCCESS) {
goto failed;
}
+13 -6
View File
@@ -92,7 +92,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const c
diff = fchan->history[hindex].end_time - fchan->history[hindex].time;
ftdm_log_chan_ex(fchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Completed state change from %s to %s in %llums\n",
ftdm_log_chan_ex(fchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Completed state change from %s to %s in %"FTDM_TIME_FMT" ms\n",
ftdm_channel_state2str(fchan->last_state), ftdm_channel_state2str(state), diff);
@@ -209,7 +209,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_cancel_state(const char *file, const char
/* NOTE
* we could potentially also take out the channel from the pendingchans queue, but I believe is easier just leave it,
* the only side effect will be a call to ftdm_channel_advance_states() for a channel that has nothing to advance */
ftdm_log_chan_ex(fchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Cancelled state change from %s to %s in %llums\n",
ftdm_log_chan_ex(fchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Cancelled state change from %s to %s in %"FTDM_TIME_FMT" ms\n",
ftdm_channel_state2str(last_state), ftdm_channel_state2str(state), diff);
return FTDM_SUCCESS;
@@ -254,7 +254,7 @@ static ftdm_status_t ftdm_core_set_state(const char *file, const char *func, int
}
if (!ftdmchan->state_completed_interrupt) {
status = ftdm_interrupt_create(&ftdmchan->state_completed_interrupt, FTDM_INVALID_SOCKET);
status = ftdm_interrupt_create(&ftdmchan->state_completed_interrupt, FTDM_INVALID_SOCKET, FTDM_NO_FLAGS);
if (status != FTDM_SUCCESS) {
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_CRIT,
"Failed to create state change interrupt when moving from %s to %s\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state));
@@ -370,12 +370,19 @@ end:
}
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
ftdm_mutex_lock(ftdmchan->span->mutex);
ftdm_set_flag(ftdmchan->span, FTDM_SPAN_STATE_CHANGE);
if (ftdmchan->span->pendingchans) {
ftdm_queue_enqueue(ftdmchan->span->pendingchans, ftdmchan);
} else {
/* there is a potential deadlock here, if a signaling module is processing
* state changes while the ftdm_span_stop() function is called, the signaling
* thread will block until it can acquire the span lock, but the thread calling
* ftdm_span_stop() which holds the span lock is waiting on the signaling thread
* to finish ... The only reason to acquire the span lock is this flag, new
* signaling modules should use the pendingchans queue instead of this flag,
* as of today a few modules need still to be updated before we can get rid of
* this flag (ie, ftmod_libpri, ftmod_isdn, ftmod_analog) */
ftdm_set_flag_locked(ftdmchan->span, FTDM_SPAN_STATE_CHANGE);
}
ftdm_mutex_unlock(ftdmchan->span->mutex);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NONBLOCK)) {
/* the channel should not block waiting for state processing */
+47 -10
View File
@@ -73,6 +73,8 @@ struct ftdm_mutex {
struct ftdm_interrupt {
ftdm_socket_t device;
ftdm_wait_flag_t device_input_flags;
ftdm_wait_flag_t device_output_flags;
#ifdef WIN32
/* for generic interruption */
HANDLE event;
@@ -323,7 +325,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_mutex_unlock(const char *file, int line, const c
}
FT_DECLARE(ftdm_status_t) ftdm_interrupt_create(ftdm_interrupt_t **ininterrupt, ftdm_socket_t device)
FT_DECLARE(ftdm_status_t) ftdm_interrupt_create(ftdm_interrupt_t **ininterrupt, ftdm_socket_t device, ftdm_wait_flag_t device_flags)
{
ftdm_status_t status = FTDM_SUCCESS;
ftdm_interrupt_t *interrupt = NULL;
@@ -340,6 +342,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_create(ftdm_interrupt_t **ininterrupt,
}
interrupt->device = device;
interrupt->device_input_flags = device_flags;
#ifdef WIN32
interrupt->event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!interrupt->event) {
@@ -389,15 +392,16 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_wait(ftdm_interrupt_t *interrupt, int m
char pipebuf[255];
#endif
ftdm_assert_return(interrupt != NULL, FTDM_FAIL, "Condition is null!\n");
ftdm_assert_return(interrupt != NULL, FTDM_FAIL, "Interrupt is null!\n");
interrupt->device_output_flags = FTDM_NO_FLAGS;
/* start implementation */
#ifdef WIN32
ints[0] = interrupt->event;
if (interrupt->device != FTDM_INVALID_SOCKET) {
num++;
ints[1] = interrupt->device;
ftdm_log(FTDM_LOG_CRIT, "implement me! (Windows support for device_output_flags member!)\n");
}
res = WaitForMultipleObjects(num, ints, FALSE, ms >= 0 ? ms : INFINITE);
switch (res) {
@@ -422,7 +426,7 @@ pollagain:
if (interrupt->device != FTDM_INVALID_SOCKET) {
num++;
ints[1].fd = interrupt->device;
ints[1].events = POLLIN;
ints[1].events = interrupt->device_input_flags;
ints[1].revents = 0;
}
@@ -446,7 +450,17 @@ pollagain:
ftdm_log(FTDM_LOG_CRIT, "reading interrupt descriptor failed (%s)\n", strerror(errno));
}
}
if (interrupt->device != FTDM_INVALID_SOCKET) {
if (ints[1].revents & POLLIN) {
interrupt->device_output_flags |= FTDM_READ;
}
if (ints[1].revents & POLLOUT) {
interrupt->device_output_flags |= FTDM_WRITE;
}
if (ints[1].revents & POLLPRI) {
interrupt->device_output_flags |= FTDM_EVENTS;
}
}
return FTDM_SUCCESS;
#endif
}
@@ -515,10 +529,12 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
for (i = 0; i < size; i++) {
ints[i] = interrupts[i]->event;
interrupts[i]->device_output_flags = FTDM_NO_FLAGS;
if (interrupts[i]->device != FTDM_INVALID_SOCKET) {
/* WARNING: if the device is ready for data we must implement for Windows the device_output_flags member */
ints[size+numdevices] = interrupts[i]->device;
numdevices++;
ftdm_log(FTDM_LOG_CRIT, "implement me! (Windows support for device_data_ready member!)\n", size);
}
}
@@ -548,17 +564,16 @@ pollagain:
ints[i].events = POLLIN;
ints[i].revents = 0;
ints[i].fd = interrupts[i]->readfd;
interrupts[i]->device_output_flags = FTDM_NO_FLAGS;
if (interrupts[i]->device != FTDM_INVALID_SOCKET) {
ints[size+numdevices].events = POLLIN;
ints[size+numdevices].events = interrupts[i]->device_input_flags;
ints[size+numdevices].revents = 0;
ints[size+numdevices].fd = interrupts[i]->device;
numdevices++;
}
}
res = poll(ints, size + numdevices, ms);
if (res == -1) {
if (errno == EINTR) {
goto pollagain;
@@ -571,7 +586,8 @@ pollagain:
return FTDM_TIMEOUT;
}
/* check for events in the pipes, NOT in the devices */
/* check for events in the pipes and in the devices, but service only the pipes */
numdevices = 0;
for (i = 0; i < size; i++) {
if (ints[i].revents & POLLIN) {
res = read(ints[i].fd, pipebuf, sizeof(pipebuf));
@@ -579,6 +595,18 @@ pollagain:
ftdm_log(FTDM_LOG_CRIT, "reading interrupt descriptor failed (%s)\n", strerror(errno));
}
}
if (interrupts[i]->device != FTDM_INVALID_SOCKET) {
if (ints[size+numdevices].revents & POLLIN) {
interrupts[i]->device_output_flags |= FTDM_READ;
}
if (ints[size+numdevices].revents & POLLOUT) {
interrupts[i]->device_output_flags |= FTDM_WRITE;
}
if (ints[size+numdevices].revents & POLLPRI) {
interrupts[i]->device_output_flags |= FTDM_EVENTS;
}
numdevices++;
}
}
#else
/* for MacOS compilation, unused vars */
@@ -587,6 +615,15 @@ pollagain:
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_wait_flag_t) ftdm_interrupt_device_ready(ftdm_interrupt_t *interrupt)
{
#if defined(__WINDOWS__)
/* device output flags are not currently filled for Windows upon returning from a wait function */
ftdm_log(FTDM_LOG_CRIT, "IMPLEMENT ME!\n");
#endif
return interrupt->device_output_flags;
}
/* For Emacs:
* Local Variables:
* mode:c
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -473,7 +473,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
sig.span_id = ftdmchan->span_id;
sig.channel = ftdmchan;
ftdm_assert(interval != 0, NULL);
ftdm_assert(interval != 0, "Invalid interval");
if (!dial_timeout) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Not waiting for dial tone to dial number %s\n", ftdmchan->caller_data.dnis.digits);
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Anthony Minessale II
* Copyright (c) 2008-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Anthony Minessale II
* Copyright (c) 2008-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
File diff suppressed because it is too large. Load diff
+168 -128
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -469,10 +469,15 @@ static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request)
}
if (new_chan && new_chan->state == FTDM_CHANNEL_STATE_DOWN) {
isdn_data->channels_local_crv[gen->CRV] = new_chan;
struct Q931_Call *call = NULL;
memset(&new_chan->caller_data, 0, sizeof(new_chan->caller_data));
ftdm_set_flag(new_chan, FTDM_CHANNEL_OUTBOUND);
ftdm_set_state_locked(new_chan, FTDM_CHANNEL_STATE_DIALING);
call = Q931GetCallByCRV(&isdn_data->q931, gen->CRV);
Q931CallSetPrivate(call, new_chan);
switch(gen->MesType) {
case Q931mes_ALERTING:
new_chan->init_state = FTDM_CHANNEL_STATE_PROGRESS_MEDIA;
@@ -539,21 +544,17 @@ static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent *
{
Q931_TrunkInfo_t *trunk = NULL;
ftdm_isdn_data_t *isdn_data = NULL;
ftdm_span_t *zspan = NULL;
ftdm_span_t *span = priv;
assert(span);
assert(call);
assert(event);
trunk = Q931CallGetTrunk(call);
assert(trunk);
zspan = Q931CallGetPrivate(call);
if (!zspan) {
zspan = priv;
Q931CallSetPrivate(call, zspan);
}
assert(zspan);
isdn_data = zspan->signal_data;
isdn_data = span->signal_data;
assert(isdn_data);
if (Q931CallIsGlobal(call)) {
/*
@@ -575,7 +576,7 @@ static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent *
* Try to get associated zap channel
* and init sigmsg struct if there is one
*/
ftdmchan = Q931CallIsOutgoing(call) ? isdn_data->channels_local_crv[call_crv] : isdn_data->channels_remote_crv[call_crv];
ftdmchan = Q931CallGetPrivate(call);
if (ftdmchan) {
memset(&sig, 0, sizeof(ftdm_sigmsg_t));
sig.chan_id = ftdmchan->chan_id;
@@ -598,7 +599,9 @@ static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent *
return;
}
if (ftdm_channel_get_state(ftdmchan) != FTDM_CHANNEL_STATE_DOWN) {
if (ftdm_channel_get_state(ftdmchan) != FTDM_CHANNEL_STATE_DOWN &&
ftdm_channel_get_state(ftdmchan) != FTDM_CHANNEL_STATE_HANGUP_COMPLETE)
{
ftdm_log(FTDM_LOG_DEBUG, "Channel %d:%d not in DOWN state, cleaning up\n",
ftdm_channel_get_span_id(ftdmchan),
ftdm_channel_get_id(ftdmchan));
@@ -763,29 +766,23 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
assert(span != NULL);
assert(isdn_data != NULL);
/*
* Support code for the new event handling system
* Remove this as soon as we have the new api to set up calls
*/
#ifdef __OLD__
if (gen->CRV) {
struct Q931_Call *call;
call = Q931GetCallByCRV(&isdn_data->q931, gen->CRV);
if (call && !Q931CallGetPrivate(call)) {
ftdm_log(FTDM_LOG_DEBUG, "Storing reference to current span in call %d [0x%x]\n", gen->CRV, gen->CRV);
Q931CallSetPrivate(call, span);
/* ftdm channel is stored in call private */
if (call) {
ftdmchan = Q931CallGetPrivate(call);
if (!ftdmchan) {
ftdm_log(FTDM_LOG_DEBUG, "[s%d] No channel associated to call [%#x] private\n",
ftdm_span_get_id(span), Q931CallGetCRV(call));
}
}
#else
if (call && !Q931CallGetPrivate(call)) {
ftdm_log(FTDM_LOG_DEBUG, "Storing reference to current span in call %d [0x%x]\n", gen->CRV, gen->CRV);
Q931CallSetPrivate(call, span);
}
#endif
ftdm_log(FTDM_LOG_DEBUG, "Yay I got an event! Type:[%02x] Size:[%d] CRV: %d (%#hx, CTX: %s)\n", gen->MesType, gen->Size, gen->CRV, gen->CRV, gen->CRVFlag ? "Terminator" : "Originator");
#ifdef __TODO_OR_REMOVE__
ftdm_log(FTDM_LOG_DEBUG, "Yay I got an event! Type:[%02x] Size:[%d] CRV: %d (%#hx, CTX: %s)\n",
gen->MesType, gen->Size, gen->CRV, gen->CRV, gen->CRVFlag ? "Terminator" : "Originator");
#ifdef __TODO__
/*
* This code block is needed for isdn_channel_request()
* isdn_data->outbound_crv has been removed so another way to pass data around is required
*/
if (gen->CRVFlag && (caller_data = isdn_data->outbound_crv[gen->CRV])) {
if (chan_id) {
caller_data->chan_id = chan_id;
@@ -808,18 +805,10 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
return 0;
}
#endif
if (gen->CRVFlag) {
ftdmchan = isdn_data->channels_local_crv[gen->CRV];
} else {
ftdmchan = isdn_data->channels_remote_crv[gen->CRV];
}
ftdm_log(FTDM_LOG_DEBUG, "ftdmchan %x (%d:%d) source isdn_data->channels_%s_crv[%#hx]\n",
ftdm_log(FTDM_LOG_DEBUG, "ftdmchan %p (%d:%d) via CRV[%#hx]\n",
ftdmchan,
((ftdmchan) ? ftdm_channel_get_span_id(ftdmchan) : -1),
((ftdmchan) ? ftdm_channel_get_id(ftdmchan) : -1),
((gen->CRVFlag) ? "local" : "remote"),
gen->CRV);
if (gen->ProtDisc == 3) {
@@ -874,12 +863,14 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
uint32_t i;
for (i = 1; i < ftdm_span_get_chan_count(span); i++) {
ftdmchan = ftdm_span_get_channel(span, chan_id);
/* Skip channels that are down and D-Channels (#OpenZAP-39) */
if (ftdm_channel_get_state(span->channels[i]) == FTDM_CHANNEL_STATE_DOWN ||
ftdm_channel_get_type(span->channels[i]) == FTDM_CHAN_TYPE_DQ921)
if (ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DOWN ||
ftdm_channel_get_type(ftdmchan) == FTDM_CHAN_TYPE_DQ921)
continue;
ftdm_set_state_locked(span->channels[i], FTDM_CHANNEL_STATE_RESTART);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
}
}
}
@@ -898,6 +889,10 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
}
}
else if (gen->MesType == Q931mes_RELEASE_COMPLETE && ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DIALTONE) {
/* Go DOWN */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
}
else if ((gen->MesType == Q931mes_RELEASE && ftdm_channel_get_state(ftdmchan) <= FTDM_CHANNEL_STATE_UP) ||
(gen->MesType == Q931mes_RELEASE_COMPLETE && ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DIALING)) {
@@ -906,7 +901,6 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
*/
Q931ie_Cause *cause = Q931GetIEPtr(gen->Cause, gen->buf);
ftdm_sigmsg_t sig;
ftdm_status_t status;
memset(&sig, 0, sizeof(sig));
sig.span_id = ftdm_channel_get_span_id(ftdmchan);
@@ -915,14 +909,15 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
sig.channel->caller_data.hangup_cause = (cause) ? cause->Value : FTDM_CAUSE_NORMAL_UNSPECIFIED;
sig.event_id = FTDM_SIGEVENT_STOP;
status = ftdm_span_send_signal(span, &sig);
ftdm_span_send_signal(span, &sig);
ftdm_log(FTDM_LOG_DEBUG, "Received %s in state %s, requested hangup for channel %d:%d\n", what,
ftdm_channel_get_state_str(ftdmchan),
ftdm_channel_get_span_id(ftdmchan),
ftdm_channel_get_id(ftdmchan));
} else {
ftdm_log(FTDM_LOG_DEBUG, "Ignoring %s on channel %d\n", what, ftdm_channel_get_id(ftdmchan));
ftdm_log(FTDM_LOG_DEBUG, "Ignoring %s on channel %d in state %s\n", what,
ftdm_channel_get_id(ftdmchan), ftdm_channel_get_state_str(ftdmchan));
}
} else {
ftdm_log(FTDM_LOG_CRIT, "Received %s with no matching channel %d\n", what, chan_id);
@@ -983,7 +978,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
int fail_cause = 0;
int fail = 1;
if (ftdmchan && ftdmchan == isdn_data->channels_remote_crv[gen->CRV]) {
if (ftdmchan && ftdmchan == Q931CallGetPrivate(call)) {
ftdm_log(FTDM_LOG_INFO, "Duplicate SETUP message(?) for Channel %d:%d ~ %d:%d in state %s [ignoring]\n",
ftdm_channel_get_span_id(ftdmchan),
ftdm_channel_get_id(ftdmchan),
@@ -1039,7 +1034,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
}
}
if (!callednum || !strlen((char *)callednum->Digit)) {
if (!callednum || ftdm_strlen_zero((char *)callednum->Digit)) {
if (FTDM_SPAN_IS_NT(span)) {
ftdm_log(FTDM_LOG_NOTICE, "No destination number found, assuming overlap dial\n");
overlap_dial++;
@@ -1080,7 +1075,6 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
if (ftdmchan && ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DOWN) {
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(ftdmchan);
isdn_data->channels_remote_crv[gen->CRV] = ftdmchan;
memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data));
if (ftdmchan->call_data) {
@@ -1095,19 +1089,12 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
if (!overlap_dial) {
isdn_get_number(callednum, caller_data->dnis.digits);
}
#ifdef __TODO_OR_REMOVE__
ftdmchan->caller_data.CRV = gen->CRV;
#endif
#if 0 /* FIXME */
if (cplen > sizeof(caller_data->raw_data)) {
cplen = sizeof(caller_data->raw_data);
}
#endif
ftdmchan->caller_data.call_reference = gen->CRV;
Q931CallSetPrivate(call, ftdmchan);
gen->CRVFlag = !(gen->CRVFlag);
#if 0 /* FIXME */
memcpy(caller_data->raw_data, msg, cplen);
caller_data->raw_data_len = cplen;
#endif
fail = 0;
}
}
@@ -1134,7 +1121,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
}
if (ftdmchan) {
ftdm_log(FTDM_LOG_CRIT, "Channel is busy\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Channel is busy\n");
} else {
ftdm_log(FTDM_LOG_CRIT, "Failed to open channel for new setup message\n");
}
@@ -1191,7 +1178,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
case Q931mes_CALL_PROCEEDING:
{
if (ftdmchan) {
ftdm_log(FTDM_LOG_CRIT, "Received CALL PROCEEDING message for channel %d\n", ftdm_channel_get_id(ftdmchan));
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Received CALL PROCEEDING message for channel\n");
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
} else {
ftdm_log(FTDM_LOG_CRIT, "Received CALL PROCEEDING with no matching channel %d\n", chan_id);
@@ -1201,7 +1188,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
case Q931mes_CONNECT_ACKNOWLEDGE:
{
if (ftdmchan) {
ftdm_log(FTDM_LOG_DEBUG, "Received CONNECT_ACK message for channel %d\n", ftdm_channel_get_id(ftdmchan));
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Received CONNECT_ACK message for channel\n");
} else {
ftdm_log(FTDM_LOG_DEBUG, "Received CONNECT_ACK with no matching channel %d\n", chan_id);
}
@@ -1211,7 +1198,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
case Q931mes_INFORMATION:
{
if (ftdmchan) {
ftdm_log(FTDM_LOG_CRIT, "Received INFORMATION message for channel %d\n", ftdm_channel_get_id(ftdmchan));
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Received INFORMATION message for channel\n");
if (ftdm_channel_get_state(ftdmchan) == FTDM_CHANNEL_STATE_DIALTONE) {
char digit = '\0';
@@ -1305,19 +1292,25 @@ static int ftdm_isdn_921_21(void *pvt, L2UCHAR *msg, L2INT mlen)
static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
{
ftdm_isdn_data_t *isdn_data = ftdmchan->span->signal_data;
ftdm_span_t *span = ftdm_channel_get_span(ftdmchan);
ftdm_isdn_data_t *isdn_data = NULL;
ftdm_sigmsg_t sig;
ftdm_status_t status;
#if 1 /* FIXME caller_data.raw_data does not exist anymore, see docs/variables.txt for more info */
Q931mes_Generic empty_gen;
Q931mes_Generic *gen = &empty_gen;
memset(&empty_gen, 0, sizeof(empty_gen)) ;
#else
Q931mes_Generic *gen = (Q931mes_Generic *) ftdmchan->caller_data.raw_data;
#endif
struct Q931_Call *call = NULL;
Q931InitMesGeneric(gen);
isdn_data = span->signal_data;
assert(isdn_data);
call = Q931GetCallByCRV(&isdn_data->q931, ftdmchan->caller_data.call_reference);
if (call) {
gen->CRV = Q931CallGetCRV(call);
gen->CRVFlag = Q931CallGetDirection(call) == Q931_DIRECTION_INBOUND ? 1 : 0;
}
ftdm_log(FTDM_LOG_DEBUG, "%d:%d STATE [%s]\n",
ftdm_channel_get_span_id(ftdmchan),
@@ -1329,17 +1322,17 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
sig.chan_id = ftdm_channel_get_id(ftdmchan);
sig.channel = ftdmchan;
/* Acknowledge channel state change */
ftdm_channel_complete_state(ftdmchan);
switch (ftdm_channel_get_state(ftdmchan)) {
case FTDM_CHANNEL_STATE_DOWN:
{
if (gen->CRV) {
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
isdn_data->channels_local_crv[gen->CRV] = NULL;
} else {
isdn_data->channels_remote_crv[gen->CRV] = NULL;
}
Q931CallSetPrivate(call, NULL);
Q931ReleaseCRV(&isdn_data->q931, gen->CRV);
}
ftdmchan->caller_data.call_reference = 0;
ftdm_channel_close(&ftdmchan);
}
break;
@@ -1348,15 +1341,10 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_PROGRESS;
if ((status = ftdm_span_send_signal(ftdm_channel_get_span(ftdmchan), &sig) != FTDM_SUCCESS)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
}
} else {
int crv = gen->CRV;
Q931InitMesGeneric(gen);
gen->MesType = Q931mes_CALL_PROCEEDING;
gen->CRV = crv;
gen->CRVFlag = 1; /* inbound */
if (FTDM_SPAN_IS_NT(ftdm_channel_get_span(ftdmchan))) {
Q931ie_ChanID ChanID;
@@ -1396,7 +1384,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_START;
if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
}
}
}
@@ -1406,7 +1394,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_UNSPECIFIED;
sig.event_id = FTDM_SIGEVENT_RESTART;
status = ftdm_span_send_signal(span, &sig);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
@@ -1414,17 +1402,16 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
}
} else {
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
return;
}
}
gen->MesType = Q931mes_ALERTING;
gen->CRVFlag = 1; /* inbound call */
Q931Rx43(&isdn_data->q931, gen, gen->Size);
}
}
@@ -1434,21 +1421,19 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_UP;
if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
}
} else {
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
return;
}
}
gen->MesType = Q931mes_CONNECT;
gen->BearerCap = 0;
gen->CRVFlag = 1; /* inbound call */
#if 0 /* FIXME */
Q931Rx43(&isdn_data->q931, gen, ftdmchan->caller_data.raw_data_len);
#endif
Q931Rx43(&isdn_data->q931, gen, gen->Size);
}
}
break;
@@ -1560,19 +1545,18 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
gen->HLComp = Q931AppendIE(gen, (L3UCHAR *) &HLComp);
Q931Rx43(&isdn_data->q931, gen, gen->Size);
isdn_data->channels_local_crv[gen->CRV] = ftdmchan;
/*
* Support code for the new event handling system
* Remove this as soon as we have the new api to set up calls
*/
if (gen->CRV) {
struct Q931_Call *call;
call = Q931GetCallByCRV(&isdn_data->q931, gen->CRV);
if (call) {
ftdm_log(FTDM_LOG_DEBUG, "Storing reference to current span in call %d [0x%x]\n", gen->CRV, gen->CRV);
Q931CallSetPrivate(call, ftdm_channel_get_span(ftdmchan));
Q931CallSetPrivate(call, ftdmchan);
ftdmchan->caller_data.call_reference = gen->CRV;
}
}
}
@@ -1585,7 +1569,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
Q931Rx43(&isdn_data->q931, gen, gen->Size);
}
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
}
break;
case FTDM_CHANNEL_STATE_HANGUP:
@@ -1593,9 +1577,8 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(ftdmchan);
Q931ie_Cause cause;
ftdm_log(FTDM_LOG_DEBUG, "Hangup: Direction %s\n", ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? "Outbound" : "Inbound");
gen->CRVFlag = ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? 0 : 1;
ftdm_log(FTDM_LOG_DEBUG, "Hangup: Call direction %s\n",
ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? "Outbound" : "Inbound");
cause.IEId = Q931ie_CAUSE;
cause.Size = sizeof(Q931ie_Cause);
@@ -1612,7 +1595,13 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
* inbound call [was: number unknown (= not found in routing state)]
* (in Q.931 spec terms: Reject request)
*/
gen->MesType = Q931mes_RELEASE_COMPLETE;
if (!FTDM_SPAN_IS_NT(span)) {
gen->MesType = Q931mes_RELEASE_COMPLETE; /* TE mode: Reject call */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
} else {
gen->MesType = Q931mes_DISCONNECT; /* NT mode: Disconnect and wait */
//ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
}
//cause.Value = (unsigned char) FTDM_CAUSE_UNALLOCATED;
cause.Value = (unsigned char) caller_data->hangup_cause;
@@ -1621,8 +1610,8 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
Q931Rx43(&isdn_data->q931, gen, gen->Size);
/* we're done, release channel */
//ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
////ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
//ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
}
else if (ftdm_channel_get_last_state(ftdmchan) <= FTDM_CHANNEL_STATE_PROGRESS) {
/*
@@ -1636,7 +1625,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
Q931Rx43(&isdn_data->q931, gen, gen->Size);
/* this will be triggered by the RELEASE_COMPLETE reply */
/* ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); */
/* ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); */
}
else {
/*
@@ -1653,13 +1642,13 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
break;
case FTDM_CHANNEL_STATE_TERMINATING:
{
ftdm_log(FTDM_LOG_DEBUG, "Terminating: Direction %s\n", ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? "Outbound" : "Inbound");
ftdm_log(FTDM_LOG_DEBUG, "Terminating: Call direction %s\n",
ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? "Outbound" : "Inbound");
sig.event_id = FTDM_SIGEVENT_STOP;
status = ftdm_span_send_signal(span, &sig);
gen->MesType = Q931mes_RELEASE;
gen->CRVFlag = ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? 0 : 1;
Q931Rx43(&isdn_data->q931, gen, gen->Size);
}
default:
@@ -1679,11 +1668,8 @@ static __inline__ void check_state(ftdm_span_t *span)
if (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) {
ftdm_channel_lock(chan);
ftdm_clear_flag(chan, FTDM_CHANNEL_STATE_CHANGE);
state_advance(chan);
ftdm_channel_complete_state(chan);
ftdm_channel_unlock(chan);
}
}
@@ -1820,7 +1806,6 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
teletone_generation_session_t ts = {{{{0}}}};;
unsigned char frame[1024];
int x, interval;
int offset = 0;
ftdm_log(FTDM_LOG_DEBUG, "ISDN tones thread starting.\n");
ftdm_set_flag(isdn_data, FTDM_ISDN_TONES_RUNNING);
@@ -1865,6 +1850,7 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
for (x = 1; x <= ftdm_span_get_chan_count(span); x++) {
ftdm_channel_t *chan = ftdm_span_get_channel(span, x);
ftdm_size_t len = sizeof(frame), rlen;
ftdm_isdn_bchan_data_t *data = chan->call_data;
if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_DQ921) {
continue;
@@ -1878,7 +1864,6 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
switch (ftdm_channel_get_state(chan)) {
case FTDM_CHANNEL_STATE_DIALTONE:
{
ftdm_isdn_bchan_data_t *data = (ftdm_isdn_bchan_data_t *)chan->call_data;
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
/* check overlap dial timeout first before generating tone */
@@ -1951,13 +1936,24 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
continue;
}
/*
* Teletone operates on SLIN data (2 bytes per sample).
* Convert the length of non-SLIN codecs, so we read
* the right amount of samples from the buffer.
*/
if (chan->effective_codec != FTDM_CODEC_SLIN) {
len *= 2;
}
/* seek to current offset */
ftdm_buffer_seek(dt_buffer, offset);
ftdm_buffer_seek(dt_buffer, data->offset);
/*
* ftdm_channel_read() can read up to sizeof(frame) bytes
* (in certain situations). Avoid overflowing the stack (and smashing dt_buffer)
* if the codec is not slin and we had to double the length.
*/
len = ftdm_min(len, sizeof(frame));
rlen = ftdm_buffer_read_loop(dt_buffer, frame, len);
if (chan->effective_codec != FTDM_CODEC_SLIN) {
@@ -1969,6 +1965,12 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
codec_func = fio_slin2alaw;
}
/*
* Convert SLIN to native format (a-law/u-law),
* input size is 2 bytes per sample, output size
* (after conversion) is one byte per sample
* (= max. half the input size).
*/
if (codec_func) {
status = codec_func(frame, sizeof(frame), &rlen);
} else {
@@ -1976,7 +1978,21 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
goto done;
}
}
ftdm_channel_write(chan, frame, sizeof(frame), &rlen);
if (ftdm_channel_write(chan, frame, sizeof(frame), &rlen) == FTDM_SUCCESS) {
/*
* Advance offset in teletone buffer by amount
* of data actually written to channel.
*/
if (chan->effective_codec != FTDM_CODEC_SLIN) {
data->offset += rlen << 1; /* Teletone buffer is in SLIN (= rlen * 2) */
} else {
data->offset += rlen;
}
/* Limit offset to [0..Rate(Samples/s)-1] in SLIN (2 bytes per sample) units. */
data->offset %= (ts.rate << 1);
}
}
/*
@@ -1985,11 +2001,6 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
if (!gated) {
ftdm_sleep(interval);
}
offset += (ts.rate / (1000 / interval)) << 1;
if (offset >= ts.rate) {
offset = 0;
}
}
done:
@@ -2055,10 +2066,13 @@ static void *ftdm_isdn_run(ftdm_thread_t *me, void *obj)
break;
default:
{
errs = 0;
if (flags & FTDM_READ) {
len = sizeof(frame);
if (ftdm_channel_read(isdn_data->dchan, frame, &len) == FTDM_SUCCESS) {
if (ftdm_channel_read(isdn_data->dchan, frame, &len) != FTDM_SUCCESS) {
ftdm_log_chan_msg(isdn_data->dchan, FTDM_LOG_ERROR, "Failed to read from D-Channel\n");
continue;
}
if (len > 0) {
#ifdef HAVE_PCAP
if (isdn_pcap_capture_both(isdn_data)) {
isdn_pcap_write(isdn_data, frame, len, ISDN_PCAP_INCOMING);
@@ -2066,6 +2080,9 @@ static void *ftdm_isdn_run(ftdm_thread_t *me, void *obj)
#endif
Q921QueueHDLCFrame(&isdn_data->q921, frame, (int)len);
Q921Rx12(&isdn_data->q921);
/* Successful read, reset error counter */
errs = 0;
}
} else {
ftdm_log(FTDM_LOG_DEBUG, "No Read FLAG!\n");
@@ -2209,7 +2226,7 @@ static ftdm_state_map_t isdn_state_map = {
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_DIALTONE, FTDM_END},
{FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
{FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_DOWN, FTDM_END}
},
{
ZSD_INBOUND,
@@ -2676,11 +2693,24 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(isdn_configure_span)
isdn_data = malloc(sizeof(*isdn_data));
assert(isdn_data != NULL);
memset(isdn_data, 0, sizeof(*isdn_data));
isdn_data->mode = Q931_TE;
memset(isdn_data, 0, sizeof(*isdn_data));
dialect = Q931_Dialect_Q931;
/* Use trunk_mode span parameter to set default */
switch (ftdm_span_get_trunk_mode(span)) {
case FTDM_TRUNK_MODE_NET:
ftdm_log(FTDM_LOG_INFO, "Span '%s' [s%d] defaulting to NET mode\n",
ftdm_span_get_name(span), ftdm_span_get_id(span));
isdn_data->mode = Q931_NT;
break;
default:
ftdm_log(FTDM_LOG_INFO, "Span '%s' [s%d] defaulting to USER mode\n",
ftdm_span_get_name(span), ftdm_span_get_id(span));
isdn_data->mode = Q931_TE;
break;
}
for (i = 0; ftdm_parameters[i].var; i++) {
const char *var = ftdm_parameters[i].var;
const char *val = ftdm_parameters[i].val;
@@ -2744,6 +2774,16 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(isdn_configure_span)
digit_timeout = DEFAULT_DIGIT_TIMEOUT;
}
/* Check if modes match and log a message if they do not. Just to be on the safe side. */
if (isdn_data->mode == Q931_TE && ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_NET) {
ftdm_log(FTDM_LOG_WARNING, "Span '%s' signalling set up for TE/CPE/USER mode, while port is running in NT/NET mode. You may want to check your 'trunk_mode' settings.\n",
ftdm_span_get_name(span));
}
else if (isdn_data->mode == Q931_NT && ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_CPE) {
ftdm_log(FTDM_LOG_WARNING, "Span '%s' signalling set up for NT/NET mode, while port is running in TE/CPE/USER mode. You may want to check your 'trunk_mode' settings.\n",
ftdm_span_get_name(span));
}
/* allocate per b-chan data */
if (isdn_data->mode == Q931_NT) {
ftdm_isdn_bchan_data_t *data;
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -67,9 +67,6 @@ struct ftdm_isdn_data {
int32_t mode;
int32_t digit_timeout;
ftdm_isdn_opts_t opts;
ftdm_caller_data_t *outbound_crv[32768];
ftdm_channel_t *channels_local_crv[32768];
ftdm_channel_t *channels_remote_crv[32768];
#ifdef HAVE_PCAP
struct pcap_context *pcap;
#endif
@@ -81,7 +78,8 @@ typedef struct ftdm_isdn_data ftdm_isdn_data_t;
/* b-channel private data */
struct ftdm_isdn_bchan_data
{
int32_t digit_timeout;
ftdm_time_t digit_timeout;
int offset; /* offset in teletone buffer */
};
typedef struct ftdm_isdn_bchan_data ftdm_isdn_bchan_data_t;
File diff suppressed because it is too large. Load diff
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, Anthony Minessale II
* Copyright (c) 2009-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,18 +30,21 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
typedef enum {
SERVICE_CHANGE_STATUS_INSERVICE = 0,
SERVICE_CHANGE_STATUS_MAINTENANCE = 1,
SERVICE_CHANGE_STATUS_OUTOFSERVICE = 2
} service_change_status_t;
#ifndef FTMOD_LIBPRI_H
#define FTMOD_LIBPRI_H
#include "freetdm.h"
#include "lpwrap_pri.h"
#define OVERLAP_TIMEOUT_MS_DEFAULT 5000 /* 5 sec */
#define OVERLAP_TIMEOUT_MS_MIN 3000 /* 3 sec */
#define OVERLAP_TIMEOUT_MS_MAX 30000 /* 30 sec */
typedef enum {
SERVICE_CHANGE_STATUS_INSERVICE = 0,
SERVICE_CHANGE_STATUS_MAINTENANCE,
SERVICE_CHANGE_STATUS_OUTOFSERVICE
} service_change_status_t;
typedef enum {
FTMOD_LIBPRI_OPT_NONE = 0,
FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL = (1 << 0),
@@ -72,15 +75,41 @@ struct ftdm_libpri_data {
int mode;
int dialect;
int overlap; /*!< Overlap dial flags */
int overlap_timeout_ms; /*!< Overlap dial timeout */
unsigned int layer1;
unsigned int ton;
unsigned int service_message_support;
lpwrap_pri_t spri;
/* MSN filter */
ftdm_hash_t *msn_hash;
ftdm_mutex_t *msn_mutex;
};
typedef struct ftdm_libpri_data ftdm_libpri_data_t;
/*
* b-channel flags
*/
enum {
FTDM_LIBPRI_B_NONE = 0,
FTDM_LIBPRI_B_REMOTE_RESTART = (1 << 0), /*!< Remote triggered channel restart */
};
/**
* Per-b-channel private data
*/
struct ftdm_libpri_b_chan {
struct lpwrap_timer t302; /*!< T302 overlap receive timer */
ftdm_channel_t *channel; /*!< back-pointer to b-channel */
q931_call *call; /*!< libpri opaque call handle */
uint32_t flags; /*!< channel flags */
};
typedef struct ftdm_libpri_b_chan ftdm_libpri_b_chan_t;
#endif
/* For Emacs:
+246 -129
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, Anthony Minessale II
* Copyright (c) 2009-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,51 +36,7 @@
#include "private/ftdm_core.h"
#include "lpwrap_pri.h"
#ifndef HAVE_GETTIMEOFDAY
#ifdef WIN32
#include <mmsystem.h>
static __inline int gettimeofday(struct timeval *tp, void *nothing)
{
#ifdef WITHOUT_MM_LIB
SYSTEMTIME st;
time_t tt;
struct tm tmtm;
/* mktime converts local to UTC */
GetLocalTime (&st);
tmtm.tm_sec = st.wSecond;
tmtm.tm_min = st.wMinute;
tmtm.tm_hour = st.wHour;
tmtm.tm_mday = st.wDay;
tmtm.tm_mon = st.wMonth - 1;
tmtm.tm_year = st.wYear - 1900; tmtm.tm_isdst = -1;
tt = mktime (&tmtm);
tp->tv_sec = tt;
tp->tv_usec = st.wMilliseconds * 1000;
#else
/**
** The earlier time calculations using GetLocalTime
** had a time resolution of 10ms.The timeGetTime, part
** of multimedia apis offer a better time resolution
** of 1ms.Need to link against winmm.lib for this
**/
unsigned long Ticks = 0;
unsigned long Sec =0;
unsigned long Usec = 0;
Ticks = timeGetTime();
Sec = Ticks/1000;
Usec = (Ticks - (Sec*1000))*1000;
tp->tv_sec = Sec;
tp->tv_usec = Usec;
#endif /* WITHOUT_MM_LIB */
(void)nothing;
return 0;
}
#endif /* WIN32 */
#endif /* HAVE_GETTIMEOFDAY */
static struct lpwrap_pri_event_list LPWRAP_PRI_EVENT_LIST[] = {
static struct lpwrap_pri_event_list LPWRAP_PRI_EVENT_LIST[LPWRAP_PRI_EVENT_MAX] = {
{0, LPWRAP_PRI_EVENT_ANY, "ANY"},
{1, LPWRAP_PRI_EVENT_DCHAN_UP, "DCHAN_UP"},
{2, LPWRAP_PRI_EVENT_DCHAN_DOWN, "DCHAN_DOWN"},
@@ -103,8 +59,6 @@ static struct lpwrap_pri_event_list LPWRAP_PRI_EVENT_LIST[] = {
{19, LPWRAP_PRI_EVENT_IO_FAIL, "IO_FAIL"},
};
#define LINE "--------------------------------------------------------------------------------"
const char *lpwrap_pri_event_str(lpwrap_pri_event_t event_id)
{
if (event_id < 0 || event_id >= LPWRAP_PRI_EVENT_MAX)
@@ -170,6 +124,10 @@ static int __pri_lpwrap_write(struct pri *pri, void *buf, int buflen)
return (int)buflen;
}
/*
* Unified init function for BRI + PRI libpri spans
*/
int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int debug)
{
int ret = -1;
@@ -179,115 +137,255 @@ int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *
spri->span = span;
if (!spri->dchan) {
ftdm_log(FTDM_LOG_ERROR, "No D-Channel available, unable to create PRI\n");
ftdm_log(FTDM_LOG_ERROR, "No D-Channel available, unable to create BRI/PRI\n");
return ret;
}
if ((spri->pri = pri_new_cb(spri->dchan->sockfd, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri))) {
unsigned char buf[4] = { 0 };
size_t buflen = sizeof(buf), len = 0;
pri_set_debug(spri->pri, debug);
#ifdef HAVE_LIBPRI_AOC
pri_aoc_events_enable(spri->pri, 1);
#endif
ftdm_channel_write(spri->dchan, buf, buflen, &len);
ret = 0;
} else {
ftdm_log(FTDM_LOG_ERROR, "Unable to create PRI\n");
if (ftdm_mutex_create(&spri->timer_mutex) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Failed to create timer list mutex\n");
return ret;
}
return ret;
}
int lpwrap_init_bri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int ptp, int debug)
{
int ret = -1;
switch (ftdm_span_get_trunk_type(span)) {
case FTDM_TRUNK_E1:
case FTDM_TRUNK_J1:
case FTDM_TRUNK_T1:
spri->pri = pri_new_cb(spri->dchan->sockfd, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri);
break;
#ifdef HAVE_LIBPRI_BRI
memset(spri, 0, sizeof(struct lpwrap_pri));
spri->dchan = dchan;
spri->span = span;
if (!spri->dchan) {
ftdm_log(FTDM_LOG_ERROR, "No D-Channel available, unable to create BRI\n");
case FTDM_TRUNK_BRI:
spri->pri = pri_new_bri_cb(spri->dchan->sockfd, 1, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri);
break;
case FTDM_TRUNK_BRI_PTMP:
spri->pri = pri_new_bri_cb(spri->dchan->sockfd, 0, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri);
break;
#endif
default:
ftdm_log(FTDM_LOG_CRIT, "Invalid/unsupported trunk type '%s'\n",
ftdm_span_get_trunk_type_str(span));
ftdm_mutex_destroy(&spri->timer_mutex);
return ret;
}
if ((spri->pri = pri_new_bri_cb(spri->dchan->sockfd, ptp, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri))) {
unsigned char buf[4] = { 0 };
size_t buflen = sizeof(buf), len = 0;
if (spri->pri) {
pri_set_debug(spri->pri, debug);
#ifdef HAVE_LIBPRI_AOC
pri_aoc_events_enable(spri->pri, 1);
#endif
ftdm_channel_write(spri->dchan, buf, buflen, &len);
ret = 0;
} else {
ftdm_log(FTDM_LOG_ERROR, "Unable to create BRI\n");
ftdm_log(FTDM_LOG_CRIT, "Unable to create BRI/PRI\n");
ftdm_mutex_destroy(&spri->timer_mutex);
}
#else
ftdm_log(FTDM_LOG_ERROR, "Installed libpri version (%s) has no BRI support\n",
pri_get_version());
#endif
return ret;
}
int lpwrap_one_loop(struct lpwrap_pri *spri)
#define timeval_to_ms(x) \
(((ftdm_time_t)(x)->tv_sec * 1000) + (ftdm_time_t)((x)->tv_usec / 1000))
int lpwrap_start_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer, const uint32_t timeout_ms, timeout_handler callback)
{
fd_set rfds, efds;
struct timeval now = {0,0}, *next = NULL;
struct lpwrap_timer **prev, *cur;
if (!spri || !timer || timer->timeout)
return -1;
ftdm_log_chan(spri->dchan, FTDM_LOG_DEBUG, "-- Starting timer %p with timeout %u ms\n",
timer, timeout_ms);
timer->timeout = ftdm_current_time_in_ms() + timeout_ms;
timer->callback = callback;
timer->next = NULL;
ftdm_mutex_lock(spri->timer_mutex);
for (prev = &spri->timer_list, cur = spri->timer_list; cur; prev = &(*prev)->next, cur = cur->next) {
if (cur->timeout < timer->timeout) {
*prev = timer;
timer->next = cur;
break;
}
}
if (!cur) {
*prev = timer;
}
ftdm_mutex_unlock(spri->timer_mutex);
return 0;
}
int lpwrap_stop_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer)
{
struct lpwrap_timer **prev, *cur;
if (!spri || !timer)
return -1;
if (!timer->timeout)
return 0;
ftdm_log_chan(spri->dchan, FTDM_LOG_DEBUG, "-- Stopping timer %p\n", timer);
ftdm_mutex_lock(spri->timer_mutex);
for (prev = &spri->timer_list, cur = spri->timer_list; cur; prev = &(*prev)->next, cur = cur->next) {
if (cur == timer) {
*prev = cur->next;
break;
}
}
ftdm_mutex_unlock(spri->timer_mutex);
timer->next = NULL;
timer->timeout = 0;
timer->callback = NULL;
return 0;
}
static struct lpwrap_timer *lpwrap_timer_next(struct lpwrap_pri *spri)
{
return spri ? spri->timer_list : NULL;
}
static int lpwrap_run_expired(struct lpwrap_pri *spri, ftdm_time_t now_ms)
{
struct lpwrap_timer *expired_list = NULL;
struct lpwrap_timer **prev, *cur;
if (!spri || !spri->timer_list)
return 0;
ftdm_mutex_lock(spri->timer_mutex);
/* Move all timers to expired list */
expired_list = spri->timer_list;
for (prev = &expired_list, cur = expired_list; cur; prev = &(*prev)->next, cur = cur->next) {
if (cur->timeout > now_ms) {
*prev = NULL;
break;
}
}
/* Move non-expired timer to front of timer_list (or clear list if there are none) */
spri->timer_list = cur;
ftdm_mutex_unlock(spri->timer_mutex);
/* fire callbacks */
while ((cur = expired_list)) {
expired_list = cur->next;
if (cur->callback)
cur->callback(spri, cur);
/* stop timer */
cur->next = NULL;
cur->timeout = 0;
cur->callback = NULL;
}
return 0;
}
#define LPWRAP_MAX_TIMEOUT_MS 100
#define LPWRAP_MAX_ERRORS 2
int lpwrap_run_pri_once(struct lpwrap_pri *spri)
{
struct timeval *next = NULL;
struct lpwrap_timer *timer = NULL;
pri_event *event = NULL;
event_handler handler;
int sel;
ftdm_wait_flag_t flags;
ftdm_time_t now_ms, next_ms, timeout_ms, tmp_ms;
int ret;
if (spri->on_loop) {
if ((sel = spri->on_loop(spri)) < 0) {
return sel;
if ((ret = spri->on_loop(spri)) < 0)
return FTDM_FAIL;
}
/* Default timeout when no scheduled events are pending */
timeout_ms = LPWRAP_MAX_TIMEOUT_MS;
next_ms = 0;
now_ms = ftdm_current_time_in_ms();
/*
* Get the next scheduled timer from libpri to set the maximum timeout,
* but limit it to MAX_TIMEOUT_MS (100ms).
*/
if ((next = pri_schedule_next(spri->pri))) {
next_ms = timeval_to_ms(next);
if (now_ms >= next_ms) {
/* Already late, handle timeout */
timeout_ms = 0;
} else {
/* Calculate new timeout and limit it to MAX_TIMEOUT_MS miliseconds */
tmp_ms = ftdm_min(next_ms - now_ms, LPWRAP_MAX_TIMEOUT_MS);
timeout_ms = ftdm_min(timeout_ms, tmp_ms);
}
}
if (spri->errs >= 2) {
spri->errs = 0;
return -1;
/*
* Next lpwrap_timer timeout
*/
if ((timer = lpwrap_timer_next(spri))) {
if (now_ms >= timer->timeout) {
/* Already late, handle timeout */
timeout_ms = 0;
} else {
/* Calculate new timeout and limit it to MAX_TIMEOUT_MS miliseconds */
tmp_ms = ftdm_min(timer->timeout - now_ms, LPWRAP_MAX_TIMEOUT_MS);
timeout_ms = ftdm_min(timeout_ms, tmp_ms);
}
}
FD_ZERO(&rfds);
FD_ZERO(&efds);
/* */
if (timeout_ms > 0) {
flags = FTDM_READ | FTDM_EVENTS;
ret = ftdm_channel_wait(spri->dchan, &flags, timeout_ms);
#ifdef _MSC_VER
//Windows macro for FD_SET includes a warning C4127: conditional expression is constant
#pragma warning(push)
#pragma warning(disable:4127)
#endif
if (spri->flags & LPWRAP_PRI_ABORT)
return FTDM_SUCCESS;
FD_SET(pri_fd(spri->pri), &rfds);
FD_SET(pri_fd(spri->pri), &efds);
if (ret == FTDM_TIMEOUT) {
now_ms = ftdm_current_time_in_ms();
#ifdef _MSC_VER
#pragma warning(pop)
#endif
now.tv_sec = 0;
now.tv_usec = 100000;
sel = select(pri_fd(spri->pri) + 1, &rfds, NULL, &efds, &now);
if (!sel) {
if ((next = pri_schedule_next(spri->pri))) {
gettimeofday(&now, NULL);
if (now.tv_sec >= next->tv_sec && (now.tv_usec >= next->tv_usec || next->tv_usec <= 100000)) {
//ftdm_log(FTDM_LOG_DEBUG, "Check event\n");
if (next) {
if (next_ms < now_ms) {
ftdm_log_chan(spri->dchan, FTDM_LOG_DEBUG, "pri timer %d ms late\n",
(int)(now_ms - next_ms));
}
event = pri_schedule_run(spri->pri);
}
if (timer) {
if (timer->timeout < now_ms) {
ftdm_log_chan(spri->dchan, FTDM_LOG_DEBUG, "lpwrap timer %d ms late\n",
(int)(now_ms - timer->timeout));
}
lpwrap_run_expired(spri, now_ms);
}
} else if (flags & (FTDM_READ | FTDM_EVENTS)) {
event = pri_check_event(spri->pri);
}
} else {
/*
* Scheduled event has already expired, handle it immediately
*/
if (next) {
event = pri_schedule_run(spri->pri);
}
if (timer) {
lpwrap_run_expired(spri, now_ms);
}
} else if (sel > 0) {
event = pri_check_event(spri->pri);
}
if (spri->flags & LPWRAP_PRI_ABORT)
return FTDM_SUCCESS;
if (event) {
event_handler handler;
/* 0 is catchall event handler */
if (event->e < 0 || event->e >= LPWRAP_PRI_EVENT_MAX) {
handler = spri->eventmap[0];
@@ -303,28 +401,47 @@ int lpwrap_one_loop(struct lpwrap_pri *spri)
ftdm_log(FTDM_LOG_CRIT, "No event handler found for event %d.\n", event->e);
}
}
return sel;
return FTDM_SUCCESS;
}
int lpwrap_run_pri(struct lpwrap_pri *spri)
{
int ret = 0;
for (;;) {
if ((ret = lpwrap_one_loop(spri)) < 0) {
#ifndef WIN32 //This needs to be adressed fror WIN32 still
if (errno == EINTR){
/* Igonore an interrupted system call */
continue;
}
#endif
ftdm_log(FTDM_LOG_CRIT, "Error = %i [%s]\n", ret, strerror(errno));
while (!(spri->flags & LPWRAP_PRI_ABORT)) {
ret = lpwrap_run_pri_once(spri);
if (ret) {
ftdm_log(FTDM_LOG_ERROR, "Error = %d, [%s]\n",
ret, strerror(errno));
spri->errs++;
} else {
spri->errs = 0;
}
if (!ftdm_running())
break;
if (spri->errs >= LPWRAP_MAX_ERRORS) {
ftdm_log(FTDM_LOG_CRIT, "Too many errors on span, restarting\n");
spri->errs = 0;
break;
}
}
return ret;
}
int lpwrap_stop_pri(struct lpwrap_pri *spri)
{
spri->flags |= LPWRAP_PRI_ABORT;
return FTDM_SUCCESS;
}
int lpwrap_destroy_pri(struct lpwrap_pri *spri)
{
if (spri->timer_mutex)
ftdm_mutex_destroy(&spri->timer_mutex);
return FTDM_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, Anthony Minessale II
* Copyright (c) 2009-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -92,10 +92,14 @@ typedef enum {
} lpwrap_pri_switch_t;
typedef enum {
LPWRAP_PRI_READY = (1 << 0)
LPWRAP_PRI_READY = (1 << 0),
LPWRAP_PRI_ABORT = (1 << 1)
} lpwrap_pri_flag_t;
struct lpwrap_pri;
struct lpwrap_timer;
typedef int (*timeout_handler)(struct lpwrap_pri *, struct lpwrap_timer *);
typedef int (*event_handler)(struct lpwrap_pri *, lpwrap_pri_event_t, pri_event *);
typedef int (*loop_handler)(struct lpwrap_pri *);
@@ -108,6 +112,8 @@ struct lpwrap_pri {
event_handler eventmap[LPWRAP_PRI_EVENT_MAX];
loop_handler on_loop;
int errs;
struct lpwrap_timer *timer_list;
ftdm_mutex_t *timer_mutex;
};
typedef struct lpwrap_pri lpwrap_pri_t;
@@ -118,15 +124,21 @@ struct lpwrap_pri_event_list {
const char *name;
};
struct lpwrap_timer {
struct lpwrap_timer *next;
ftdm_time_t timeout;
timeout_handler callback;
};
int lpwrap_start_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer, const uint32_t timeout_ms, timeout_handler callback);
int lpwrap_stop_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer);
#define LPWRAP_MAP_PRI_EVENT(spri, event, func) spri.eventmap[event] = func;
const char *lpwrap_pri_event_str(lpwrap_pri_event_t event_id);
int lpwrap_one_loop(struct lpwrap_pri *spri);
int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int debug);
int lpwrap_init_bri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int ptp, int debug);
int lpwrap_run_pri(struct lpwrap_pri *spri);
#define lpwrap_run_bri(x) lpwrap_run_pri(x)
int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int debug);
int lpwrap_destroy_pri(struct lpwrap_pri *spri);
int lpwrap_run_pri_once(struct lpwrap_pri *spri);
int lpwrap_run_pri(struct lpwrap_pri *spri);
int lpwrap_stop_pri(struct lpwrap_pri *spri);
#endif
File diff suppressed because it is too large. Load diff
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -782,7 +782,7 @@ static ftdm_status_t ftdm_pritap_sig_read(ftdm_channel_t *ftdmchan, void *data,
return FTDM_FAIL;
}
if (sizeread != size) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "read from peer channel only %d bytes!\n", sizeread);
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "read from peer channel only %"FTDM_SIZE_FMT" bytes!\n", sizeread);
return FTDM_FAIL;
}
@@ -854,7 +854,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_pritap_configure_span)
}
if (!dchan) {
ftdm_log(FTDM_LOG_ERROR, "No d-channel specified in freetdm.conf!\n", ftdm_trunk_type2str(span->trunk_type));
ftdm_log(FTDM_LOG_ERROR, "No d-channel specified in freetdm.conf!\n");
return FTDM_FAIL;
}
+3 -3
View File
@@ -1557,10 +1557,10 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
intval = atoi(val);
if (intval < 0) {
r2conf.mf_dump_size = FTDM_IO_DUMP_DEFAULT_BUFF_SIZE;
ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with default mf_dump_size = %d bytes\n", span->name, r2conf.mf_dump_size);
ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with default mf_dump_size = %"FTDM_SIZE_FMT" bytes\n", span->name, r2conf.mf_dump_size);
} else {
r2conf.mf_dump_size = intval;
ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with mf_dump_size = %d bytes\n", span->name, r2conf.mf_dump_size);
ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with mf_dump_size = %"FTDM_SIZE_FMT" bytes\n", span->name, r2conf.mf_dump_size);
}
} else if (!strcasecmp(var, "allow_collect_calls")) {
r2conf.allow_collect_calls = ftdm_true(val);
@@ -1970,7 +1970,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
r2data->monitor_thread_id = syscall(SYS_gettid);
#endif
ftdm_log(FTDM_LOG_DEBUG, "OpenR2 monitor thread %lu started.\n", r2data->monitor_thread_id);
ftdm_log(FTDM_LOG_DEBUG, "OpenR2 monitor thread %u started.\n", r2data->monitor_thread_id);
r2chan = NULL;
chaniter = ftdm_span_get_chan_iterator(span, NULL);
if (!chaniter) {
@@ -451,17 +451,17 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
/* get an interrupt queue for this span */
if (ftdm_queue_get_interrupt(span->pendingchans, &ftdm_sangoma_isdn_int[0]) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a ftdm_interrupt for span = %s!\n", span->name);
ftdm_log(FTDM_LOG_CRIT, "Failed to get a ftdm_interrupt for span = %s!\n", span->name);
goto ftdm_sangoma_isdn_run_exit;
}
if (ftdm_queue_get_interrupt(span->pendingsignals, &ftdm_sangoma_isdn_int[1]) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a signal interrupt for span = %s!\n", span->name);
ftdm_log(FTDM_LOG_CRIT, "Failed to get a signal interrupt for span = %s!\n", span->name);
goto ftdm_sangoma_isdn_run_exit;
}
if (ftdm_queue_get_interrupt(signal_data->event_queue, &ftdm_sangoma_isdn_int[2]) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a event interrupt for span = %s!\n", span->name);
ftdm_log(FTDM_LOG_CRIT, "Failed to get a event interrupt for span = %s!\n", span->name);
goto ftdm_sangoma_isdn_run_exit;
}
@@ -528,6 +528,7 @@ ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb);
ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb);
ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt);
ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
ftdm_status_t set_called_subaddr(ftdm_channel_t *ftdmchan, CdPtySad *cdPtySad);
ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind);
ftdm_status_t set_bear_cap_ie(ftdm_channel_t *ftdmchan, BearCap *bearCap);
ftdm_status_t set_network_specific_fac(ftdm_channel_t *ftdmchan, NetFac *netFac);
@@ -131,7 +131,7 @@ static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span
/* can be > 1 for some BRI variants */
break;
default:
ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type));
ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported trunktype:%s\n", span->name, ftdm_trunk_type2str(span->trunk_type));
return FTDM_FAIL;
}
@@ -523,7 +523,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
parse_yesno(var, val, &signal_data->restart_opt);
} else if (!strcasecmp(var, "channel-restart-timeout")) {
signal_data->restart_timeout = atoi(val);
} else if (!strcasecmp(var, "local-number")) {
} else if (!strcasecmp(var, "local-number")) {
if (add_local_number(val, span) != FTDM_SUCCESS) {
return FTDM_FAIL;
}
@@ -719,7 +719,11 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.clrGlr = FALSE; /* in case of glare, do not clear local call */
cfg.t.cfg.s.inDLSAP.statEnqOpt = TRUE;
cfg.t.cfg.s.inDLSAP.rstOpt = TRUE;
if (signal_data->ftdm_span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
cfg.t.cfg.s.inDLSAP.rstOpt = FALSE;
} else {
cfg.t.cfg.s.inDLSAP.rstOpt = TRUE;
}
} else {
cfg.t.cfg.s.inDLSAP.ackOpt = FALSE;
cfg.t.cfg.s.inDLSAP.intType = USER;
@@ -841,19 +845,17 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.tmr.t308.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t308.val = 4;
cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t310.val = 120;
if (signal_data->timer_t308 > 0) {
cfg.t.cfg.s.inDLSAP.tmr.t308.val = signal_data->timer_t308;
}
if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t310.val = 10;
cfg.t.cfg.s.inDLSAP.tmr.t312.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t312.val = cfg.t.cfg.s.inDLSAP.tmr.t303.val+2;
} else {
cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t310.val = 120;
cfg.t.cfg.s.inDLSAP.tmr.t312.enb = FALSE;
}
@@ -967,7 +969,7 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.dChannelNum = 0; /* Unused for BRI */
cfg.t.cfg.s.inDLSAP.nmbBearChan = NUM_BRI_CHANNELS_PER_SPAN;
cfg.t.cfg.s.inDLSAP.firstBChanNum = 1;
cfg.t.cfg.s.inDLSAP.callRefLen = 1;
cfg.t.cfg.s.inDLSAP.callRefLen = 1;
cfg.t.cfg.s.inDLSAP.teiAlloc = IN_STATIC;
cfg.t.cfg.s.inDLSAP.intCfg = IN_INTCFG_PTPT;
break;
@@ -1023,7 +1025,13 @@ ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span)
cfg.t.cfg.s.inLCe.sapId = signal_data->link_id;
cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE;
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
/* Stack will send Restart CFM's each time link is established (TEI negotiated),
and we do not want thi s event */
cfg.t.cfg.s.inLCe.lnkUpDwnInd = FALSE;
} else {
cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE;
}
if (FTDM_SPAN_IS_BRI(span)) {
/* tCon Timer causes unwanted hangup on BRI links
@@ -1225,7 +1233,7 @@ uint8_t sng_isdn_stack_switchtype(sngisdn_switchtype_t switchtype)
case SNGISDN_SWITCH_INSNET:
return SW_INSNET;
case SNGISDN_SWITCH_INVALID:
ftdm_log(FTDM_LOG_ERROR, "%s:Invalid switchtype:%d\n", switchtype);
ftdm_log(FTDM_LOG_ERROR, "Invalid switchtype: %d\n", switchtype);
break;
}
return 0;
@@ -493,7 +493,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
if (cnStEvnt->sndCmplt.eh.pres || num_digits >= min_digits) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
} else {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "received %d of %d digits\n", num_digits, min_digits);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "received %"FTDM_SIZE_FMT" of %"FTDM_SIZE_FMT" digits\n", num_digits, min_digits);
}
}
break;
@@ -509,7 +509,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "\n", suId, suInstId, spInstId);
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unhandled INFO (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
break;
}
}
@@ -966,6 +966,12 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
break;
case 2: /* overlap sending */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_COLLECT:
/* T302 Timeout reached */
/* Send the call to user, and see if they accept it */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T302 Timer expired, proceeding with call\n");
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
break;
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_RINGING:
@@ -1196,7 +1202,16 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
return;
}
if (rstEvnt->rstInd.eh.pres == PRSNT_NODEF && rstEvnt->rstInd.rstClass.pres == PRSNT_NODEF) {
ftdm_log(FTDM_LOG_DEBUG, "%s: Processing RESTART CFM (suId:%u dChan:%d ces:%d %s(%d))\n",
signal_data->ftdm_span->name,
suId, dChan, ces,
(evntType == IN_LNK_DWN)?"LNK_DOWN":
(evntType == IN_LNK_UP)?"LNK_UP":
(evntType == IN_INDCHAN)?"b-channel":
(evntType == IN_LNK_DWN_DM_RLS)?"NFAS service procedures":
(evntType == IN_SWCHD_BU_DCHAN)?"NFAS switchover to backup":"Unknown", evntType);
if (rstEvnt->rstInd.eh.pres == PRSNT_NODEF && rstEvnt->rstInd.rstClass.pres == PRSNT_NODEF) {
switch(rstEvnt->rstInd.rstClass.val) {
case IN_CL_INDCHAN: /* Indicated b-channel */
if (rstEvnt->chanId.eh.pres) {
@@ -1342,28 +1357,29 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
}
if (chan_no) { /* For a single channel */
if (chan_no > ftdm_span_get_chan_count(signal_data->ftdm_span)) {
ftdm_log(FTDM_LOG_CRIT, "Received RESTART IND on invalid channel:%d\n", chan_no);
} else {
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
if (ftdmchan->physical_chan_id == chan_no) {
sngisdn_bring_down(ftdmchan);
}
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
if (sngisdn_info->ces == ces && ftdmchan->physical_chan_id == chan_no) {
sngisdn_bring_down(ftdmchan);
}
ftdm_iterator_free(chaniter);
}
ftdm_iterator_free(chaniter);
} else { /* for all channels */
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
sngisdn_bring_down((ftdm_channel_t*)ftdm_iterator_current(curr));
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
if (sngisdn_info->ces == ces) {
sngisdn_bring_down(ftdmchan);
}
}
ftdm_iterator_free(chaniter);
}
@@ -67,6 +67,7 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
set_calling_num(ftdmchan, &conEvnt.cgPtyNmb);
set_calling_num2(ftdmchan, &conEvnt.cgPtyNmb2);
set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad);
set_called_subaddr(ftdmchan, &conEvnt.cdPtySad);
set_redir_num(ftdmchan, &conEvnt.redirNmb);
set_calling_name(ftdmchan, &conEvnt);
set_network_specific_fac(ftdmchan, &conEvnt.netFac[0]);
@@ -1084,7 +1084,7 @@ void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...)
switch (level) {
case SNG_LOGLEVEL_DEBUG:
ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s\n", data);
break;
case SNG_LOGLEVEL_WARN:
if ( strncmp(data, "Invalid Q.921/Q.931 frame", 25) ) {
@@ -1092,21 +1092,21 @@ void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...)
}
break;
case SNG_LOGLEVEL_INFO:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data);
break;
case SNG_LOGLEVEL_STATS:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data);
break;
case SNG_LOGLEVEL_ERROR:
ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s\n", data);
/*ftdm_assert(0, "Got an error from stack");*/
break;
case SNG_LOGLEVEL_CRIT:
ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s\n", data);
/* ftdm_assert(0, "Got an error from stack"); */
break;
default:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data);
break;
}
ftdm_safe_free(data);
@@ -453,7 +453,7 @@ ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
}
memset(subaddress, 0, sizeof(subaddress));
if(cgPtySad->sadInfo.len >= sizeof(subaddress)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Calling Party Subaddress exceeds local size limit (len:%d max:%d)\n", cgPtySad->sadInfo.len, sizeof(subaddress));
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Calling Party Subaddress exceeds local size limit (len:%d max:%"FTDM_SIZE_FMT")\n", cgPtySad->sadInfo.len, sizeof(subaddress));
cgPtySad->sadInfo.len = sizeof(subaddress)-1;
}
@@ -847,6 +847,26 @@ ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
return FTDM_SUCCESS;
}
ftdm_status_t set_called_subaddr(ftdm_channel_t *ftdmchan, CdPtySad *cdPtySad)
{
const char* cld_subaddr = NULL;
cld_subaddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.called_subaddr");
if (!ftdm_strlen_zero(cld_subaddr)) {
unsigned len = strlen (cld_subaddr);
cdPtySad->eh.pres = PRSNT_NODEF;
cdPtySad->typeSad.pres = 1;
cdPtySad->typeSad.val = 0; /* NSAP */
cdPtySad->oddEvenInd.pres = 1;
cdPtySad->oddEvenInd.val = 0;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Called Party Subaddress:%s\n", cld_subaddr);
cdPtySad->sadInfo.pres = 1;
cdPtySad->sadInfo.len = len;
memcpy(cdPtySad->sadInfo.val, cld_subaddr, len);
}
return FTDM_SUCCESS;
}
ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr)
{
ftdm_status_t status;
@@ -1198,7 +1218,7 @@ void sngisdn_restart_timeout(void *p_signal_data)
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
ftdm_log(FTDM_LOG_DEBUG, "s%d:Did not receive a RESTART from remote switch in %d ms - restarting\n", span->name, signal_data->restart_timeout);
ftdm_log(FTDM_LOG_DEBUG, "s%s:Did not receive a RESTART from remote switch in %d ms - restarting\n", span->name, signal_data->restart_timeout);
chaniter = ftdm_span_get_chan_iterator(span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
@@ -152,7 +152,7 @@ static ftdm_status_t att_courtesy_vru(ftdm_channel_t *ftdmchan, sngisdn_transfer
goto done;
}
if (strlen(val) > COURTESY_TRANSFER_MAX_DATA_SIZE) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Data exceeds max size (len:%d max:%d), cannot perform transfer\n", strlen(val), COURTESY_TRANSFER_MAX_DATA_SIZE);
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Data exceeds max size (len:%"FTDM_SIZE_FMT" max:%d), cannot perform transfer\n", strlen(val), COURTESY_TRANSFER_MAX_DATA_SIZE);
goto done;
}
memcpy(sngisdn_info->transfer_data.tdata.att_courtesy_vru.data, val, strlen(val));
@@ -99,17 +99,18 @@ int ft_to_sngss7_cfg_all(void)
return 1;
} else {
SS7_INFO("Started Stack Manager!\n");
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM_STARTED);
}
/* check if the configuration had a Relay Channel */
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY_PRESENT)) {
/* start up the relay task */
if (sng_isup_init_relay()) {
SS7_CRITICAL("Failed to start Relay\n");
return 1;
} else {
SS7_INFO("Started Relay!\n");
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY_STARTED);
}
/* run general configuration on the relay task */
@@ -122,12 +123,13 @@ int ft_to_sngss7_cfg_all(void)
} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY)) */
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_PRESENT)) {
if (sng_isup_init_cc()) {
SS7_CRITICAL("Failed to start Call-Control\n");
return 1;
} else {
SS7_INFO("Started Call-Control!\n");
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_STARTED);
}
if (ftmod_ss7_cc_gen_config()) {
SS7_CRITICAL("CC General configuration FAILED!\n");
@@ -143,12 +145,13 @@ int ft_to_sngss7_cfg_all(void)
}
} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC)) */
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_PRESENT)) {
if (sng_isup_init_isup()) {
SS7_CRITICAL("Failed to start ISUP\n");
return 1;
} else {
SS7_INFO("Started ISUP!\n");
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_STARTED);
}
if (ftmod_ss7_isup_gen_config()) {
SS7_CRITICAL("ISUP General configuration FAILED!\n");
@@ -158,12 +161,13 @@ int ft_to_sngss7_cfg_all(void)
}
} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) */
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3_PRESENT)) {
if (sng_isup_init_mtp3()) {
SS7_CRITICAL("Failed to start MTP3\n");
return 1;
} else {
SS7_INFO("Started MTP3!\n");
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3_STARTED);
}
if (ftmod_ss7_mtp3_gen_config()) {
@@ -174,18 +178,20 @@ int ft_to_sngss7_cfg_all(void)
}
} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3)) */
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_PRESENT)) {
if (sng_isup_init_mtp2()) {
SS7_CRITICAL("Failed to start MTP2\n");
return 1;
} else {
SS7_INFO("Started MTP2!\n");
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_STARTED);
}
if (sng_isup_init_mtp1()) {
SS7_CRITICAL("Failed to start MTP2\n");
SS7_CRITICAL("Failed to start MTP1\n");
return 1;
} else {
SS7_INFO("Started MTP1!\n");
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP1_STARTED);
}
if (ftmod_ss7_mtp1_gen_config()) {
SS7_CRITICAL("MTP1 General configuration FAILED!\n");
@@ -376,7 +382,7 @@ int ft_to_sngss7_cfg_all(void)
x++;
} /* while (x < (MAX_ISAPS)) */
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_STARTED)) {
x = 1;
while (x < (MAX_ISUP_INFS)) {
/* check if this link has been configured already */
@@ -913,13 +919,14 @@ int ftmod_ss7_mtp3_dlsap_config(int id)
#endif /* SDT2 */
cfg.t.cfg.s.snDLSAP.lnkId = 0; /* signalling link allocation procedure identity */
cfg.t.cfg.s.snDLSAP.lnkTstSLC = k->slc; /* link selection code for link test */
cfg.t.cfg.s.snDLSAP.tstLen = 6; /* link test pattern length */
cfg.t.cfg.s.snDLSAP.tst[0] = 'K'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[1] = 'O'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tstLen = 7; /* link test pattern length */
cfg.t.cfg.s.snDLSAP.tst[0] = 'S'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[1] = 'A'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[2] = 'N'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[3] = 'R'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[4] = 'A'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[5] = 'D'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[3] = 'G'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[4] = 'O'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[5] = 'M'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.tst[6] = 'A'; /* link test pattern */
cfg.t.cfg.s.snDLSAP.ssf = k->ssf; /* sub service field */
cfg.t.cfg.s.snDLSAP.dstProcId = k->mtp2ProcId; /* destination processor id */
cfg.t.cfg.s.snDLSAP.dstEnt = ENTSD; /* entity */
File diff suppressed because it is too large. Load diff
@@ -89,12 +89,13 @@ ftdm_status_t handle_olm_msg(uint32_t suInstId, uint32_t spInstId, uint32_t circ
ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt)
{
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
char nadi[2];
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
memset(nadi, '\0', sizeof(nadi));
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
char var[FTDM_DIGITS_LIMIT];
memset(var, '\0', sizeof(var));
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
@@ -209,12 +210,52 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
}
/* add any special variables for the dialplan */
sprintf(nadi, "%d", siConEvnt->cgPtyNum.natAddrInd.val);
sngss7_add_var(sngss7_info, "ss7_clg_nadi", nadi);
sprintf(var, "%d", siConEvnt->cgPtyNum.natAddrInd.val);
sngss7_add_var(sngss7_info, "ss7_clg_nadi", var);
sprintf(nadi, "%d", siConEvnt->cdPtyNum.natAddrInd.val);
sngss7_add_var(sngss7_info, "ss7_cld_nadi", nadi);
sprintf(var, "%d", siConEvnt->cdPtyNum.natAddrInd.val);
sngss7_add_var(sngss7_info, "ss7_cld_nadi", var);
/* Retrieve the Location Number if present (see ITU Q.763, 3.30) */
if (siConEvnt->cgPtyNum1.eh.pres) {
if (siConEvnt->cgPtyNum1.addrSig.pres) {
/* fill in the ss7 location address number */
copy_tknStr_from_sngss7(siConEvnt->cgPtyNum1.addrSig, var, siConEvnt->cgPtyNum1.oddEven);
sngss7_add_var(sngss7_info, "ss7_loc_digits", var);
}
if (siConEvnt->cgPtyNum1.scrnInd.pres) {
/* fill in the screening indication value */
sprintf(var, "%d", siConEvnt->cgPtyNum1.scrnInd.val);
sngss7_add_var(sngss7_info, "ss7_loc_screen_ind", var);
}
if (siConEvnt->cgPtyNum1.presRest.pres) {
/* fill in the presentation value */
sprintf(var, "%d", siConEvnt->cgPtyNum1.presRest.val);
sngss7_add_var(sngss7_info, "ss7_loc_pres_ind", var);
}
if (siConEvnt->cgPtyNum1.natAddrInd.pres) {
sprintf(var, "%d", siConEvnt->cgPtyNum1.natAddrInd.val);
sngss7_add_var(sngss7_info, "ss7_loc_nadi", var);
}
} else {
SS7_DEBUG_CHAN(ftdmchan, "No Location Number information in IAM%s\n", " ");
}
sprintf(var, "%d", sngss7_info->circuit->cic);
sngss7_add_var(sngss7_info, "ss7_cic", var);
sprintf(var, "%d", g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].spc );
sngss7_add_var(sngss7_info, "ss7_opc", var);
if (siConEvnt->callRef.callId.pres) {
ftdmchan->caller_data.call_reference = (unsigned int)siConEvnt->callRef.callId.val;
} else {
ftdmchan->caller_data.call_reference = 0;
}
if (sngss7_info->circuit->transparent_iam) {
sngss7_save_iam(ftdmchan, siConEvnt);
}
@@ -252,9 +293,9 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
case (FTDM_CHANNEL_STATE_HANGUP_COMPLETE):
handle_glare:
/* the core already has plans for this channel...glare */
SS7_INFO_CHAN(ftdmchan, "Got IAM on channel that is already inuse (state=%s|inuse=%d)...glare!\n",
SS7_INFO_CHAN(ftdmchan, "Got IAM on channel that is already inuse (state=%s|inuse=%c)...glare!\n",
ftdm_channel_state2str (ftdmchan->state),
ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE));
ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE) ? 'Y' : 'N');
/* save the info so that we can use it later on */
sngss7_info->glare.spInstId = spInstId;
@@ -401,6 +442,8 @@ ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circ
append_tknStr_from_sngss7(siCnStEvnt->subNum.addrSig,
ftdmchan->caller_data.dnis.digits,
siCnStEvnt->subNum.oddEven);
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Rx SAM (digits = %s)\n", sngss7_info->circuit->cic,
ftdmchan->caller_data.dnis.digits);
} else {
SS7_INFO_CHAN(ftdmchan,"No Called party (DNIS) information in SAM!%s\n", " ");
}
@@ -696,7 +739,7 @@ ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
* ITU Q.784 Test Number 3.8
* Collision of REL messages
*/
SS7_DEBUG_CHAN(ftdmchan, "Collision of REL messages. Rx REL while waiting for RLC.\n", " ");
SS7_DEBUG_CHAN(ftdmchan, "Collision of REL messages. Rx REL while waiting for RLC.%s\n", " ");
if (sngss7_test_ckt_flag(sngss7_info, FLAG_LOCAL_REL) &&
!sngss7_test_ckt_flag (sngss7_info, FLAG_REMOTE_REL)) {
/* locally requested hangup completed, wait for remote RLC */
@@ -1639,8 +1682,8 @@ ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
ftdm_mutex_lock(ftdmchan->mutex);
/* check if the channel is blocked */
if (!(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX))) {
SS7_WARN("Received UBL on circuit that is not blocked!\n");
if (!(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) && !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) {
SS7_WARN("Received UBL on circuit that is not blocked! span= %d, chan= %d , flag = %x \n", g_ftdm_sngss7_data.cfg.isupCkt[circuit].span, g_ftdm_sngss7_data.cfg.isupCkt[circuit].chan,sngss7_info->blk_flags );
}
/* throw the unblock flag */
@@ -1648,6 +1691,8 @@ ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* clear the block flag */
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX_DN);
/* set the channel to suspended state */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
@@ -1688,14 +1733,6 @@ ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
DECODE_LCC_EVENT(evntType));
}
/* lock the channel */
ftdm_mutex_lock(ftdmchan->mutex);
/* KONRAD FIX ME */
/* unlock the channel again before we exit */
ftdm_mutex_unlock(ftdmchan->mutex);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return FTDM_SUCCESS;
}
@@ -1860,7 +1897,7 @@ ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* go to DOWN */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
} else {
SS7_ERROR("Received RSC-RLC but we're not waiting on a RSC-RLC on CIC #, dropping\n", sngss7_info->circuit->cic);
SS7_ERROR("Received RSC-RLC but we're not waiting on a RSC-RLC on CIC #%d, dropping\n", sngss7_info->circuit->cic);
}
break;
@@ -2449,6 +2486,8 @@ ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/**********************************************************************/
case 0: /* maintenance oriented */
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN);
break;
/**********************************************************************/
case 1: /* hardware failure oriented */
@@ -486,47 +486,47 @@ void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint
g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic);
}
x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
x = (g_ftdm_sngss7_data.cfg.procId * MAX_CIC_MAP_LENGTH) + 1;
while ((g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) &&
(g_ftdm_sngss7_data.cfg.isupCkt[x].id < ((g_ftdm_sngss7_data.cfg.procId +1) * 1000))) {
/**********************************************************************/
(g_ftdm_sngss7_data.cfg.isupCkt[x].id < ((g_ftdm_sngss7_data.cfg.procId + 1) * MAX_CIC_MAP_LENGTH))) {
/**********************************************************************/
/* confirm this is a voice channel and not a gap/sig (no ftdmchan there) */
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type != SNG_CKT_VOICE) goto move_along;
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) {
/* compare the intfIds */
if (g_ftdm_sngss7_data.cfg.isupCkt[x].infId == intfId) {
/* we have a match, setup the pointers to the correct values */
circuit = x;
/* compare the intfIds */
if (g_ftdm_sngss7_data.cfg.isupCkt[x].infId == intfId) {
/* we have a match, setup the pointers to the correct values */
circuit = x;
/* confirm that the circuit is active on our side otherwise move to the next circuit */
if (!sngss7_test_flag(&g_ftdm_sngss7_data.cfg.isupCkt[circuit], SNGSS7_ACTIVE)) {
SS7_DEBUG("[CIC:%d]Rx %s but circuit is not active yet, skipping!\n",
g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic,
DECODE_LCC_EVENT(evntType));
x++;
continue;
}
/* confirm that the circuit is active on our side otherwise move to the next circuit */
if (!sngss7_test_flag(&g_ftdm_sngss7_data.cfg.isupCkt[circuit], SNGSS7_ACTIVE)) {
SS7_DEBUG("[CIC:%d]Rx %s but circuit is not active yet, skipping!\n",
g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic,
DECODE_LCC_EVENT(evntType));
continue;
}
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
/* bounce out of the loop */
break;
}
}
/* bounce out of the loop */
break;
} /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].intfId == intfId) */
move_along:
/* move along ... nothing to see here */
x++;
/**********************************************************************/
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
/**********************************************************************/
}
/* check if we found any circuits that are on the intfId, drop the message
* if none are found
*/
if (ftdmchan == NULL) goto sta_ind_end;
* if none are found */
if (!ftdmchan) {
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
break;
/**************************************************************************/
@@ -544,7 +544,6 @@ move_along:
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
break;
/**************************************************************************/
} /* switch (evntType) */
@@ -571,9 +570,6 @@ move_along:
/* enqueue this event */
ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
sta_ind_end:
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
/******************************************************************************/
@@ -31,6 +31,7 @@
* SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* INCLUDE ********************************************************************/
#include "ftmod_sangoma_ss7_main.h"
/******************************************************************************/
@@ -279,7 +280,7 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtp2Link[x].name);
}
ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s %s : %d\n",
ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s %s : %s\n",
buf,
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_DISC_REASON(sta->t.usta.evntParm[1]));
@@ -353,6 +354,8 @@ void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta)
char buf[50];
int x = 1;
SS7_RELAY_DBG_FUN(handle_sng_mtp3_alarm);
memset(buf, '\0', sizeof(buf));
switch (sta->hdr.elmId.elmnt) {
@@ -492,6 +495,8 @@ void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
char tmp[25];
char *p = NULL;
int x = 0;
SS7_RELAY_DBG_FUN(handle_sng_isup_alarm);
/* initalize the msg variable to NULLs */
memset(&msg[0], '\0', sizeof(&msg));
@@ -502,7 +507,6 @@ void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
return;
}
/* point p to the first spot in msg */
p = &msg[0];
@@ -742,6 +746,7 @@ void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta)
{
SS7_RELAY_DBG_FUN(handle_sng_cc_alarm);
return;
} /* handle_cc_alarm */
@@ -749,6 +754,7 @@ void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta)
void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta)
{
SS7_RELAY_DBG_FUN(handle_sng_relay_alarm);
switch (sta->hdr.elmId.elmnt) {
/**************************************************************************/
@@ -60,6 +60,7 @@ static ftdm_status_t ftdm_sangoma_ss7_stop (ftdm_span_t * span);
static ftdm_status_t ftdm_sangoma_ss7_start (ftdm_span_t * span);
/******************************************************************************/
/* STATE MAP ******************************************************************/
ftdm_state_map_t sangoma_ss7_state_map = {
{
@@ -281,7 +282,37 @@ ftdm_state_map_t sangoma_ss7_state_map = {
}
};
/******************************************************************************/
static void handle_hw_alarm(ftdm_event_t *e)
{
sngss7_chan_data_t *ss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
int x = 0;
ftdm_assert(e != NULL, "Null event!\n");
for (x = (g_ftdm_sngss7_data.cfg.procId * MAX_CIC_MAP_LENGTH) + 1; g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0; x++) {
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) {
ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
ftdmchan = ss7_info->ftdmchan;
if (e->channel->span_id == ftdmchan->physical_span_id &&
e->channel->chan_id == ftdmchan->physical_chan_id) {
if (e->enum_id == FTDM_OOB_ALARM_TRAP) {
sngss7_set_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX);
if (ftdmchan->state != FTDM_CHANNEL_STATE_SUSPENDED) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
}
} else {
sngss7_set_ckt_blk_flag(ss7_info, FLAG_GRP_HW_UNBLK_TX);
sngss7_clear_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX);
if (ftdmchan->state != FTDM_CHANNEL_STATE_SUSPENDED) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
}
}
}
}
}
}
/* MONITIOR THREADS ***********************************************************/
static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
@@ -293,6 +324,9 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
sngss7_event_data_t *sngss7_event = NULL;
sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
int b_alarm_test = 1;
sngss7_chan_data_t *ss7_info=NULL;
ftdm_log (FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u started.\n", ftdmspan->span_id);
/* set IN_THREAD flag so that we know this thread is running */
@@ -311,6 +345,30 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
}
while (ftdm_running () && !(ftdm_test_flag (ftdmspan, FTDM_SPAN_STOP_THREAD))) {
int x = 0;
if (b_alarm_test) {
b_alarm_test = 0;
for (x = (g_ftdm_sngss7_data.cfg.procId * MAX_CIC_MAP_LENGTH) + 1;
g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0; x++) {
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) {
ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
ftdmchan = ss7_info->ftdmchan;
if (!ftdmchan) {
continue;
}
if (ftdmchan->alarm_flags != 0) { /* we'll send out block */
sngss7_set_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX );
} else { /* we'll send out reset */
sngss7_clear_ckt_blk_flag( ss7_info, FLAG_GRP_HW_BLOCK_TX );
sngss7_clear_ckt_blk_flag( ss7_info, FLAG_GRP_HW_BLOCK_TX_DN );
sngss7_set_ckt_blk_flag (ss7_info, FLAG_GRP_HW_UNBLK_TX);
}
}
usleep(50);
}
ftdmchan = NULL;
}
/* check the channel state queue for an event*/
switch ((ftdm_interrupt_multiple_wait(ftdm_sangoma_ss7_int, 2, 100))) {
@@ -388,7 +446,11 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
switch (ftdm_span_poll_event(ftdmspan, 0, NULL)) {
/**********************************************************************/
case FTDM_SUCCESS:
while (ftdm_span_next_event(ftdmspan, &event) == FTDM_SUCCESS);
while (ftdm_span_next_event(ftdmspan, &event) == FTDM_SUCCESS) {
if (event->e_type == FTDM_EVENT_OOB) {
handle_hw_alarm(event);
}
}
break;
/**********************************************************************/
case FTDM_TIMEOUT:
@@ -530,6 +592,11 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
i++;
}
/* kill t10 if active */
if (sngss7_info->t10.hb_timer_id) {
ftdm_sched_cancel_timer (sngss7_info->t10.sched, sngss7_info->t10.hb_timer_id);
}
/* check if the end of pulsing (ST) character has arrived or the right number of digits */
if (ftdmchan->caller_data.dnis.digits[i-1] == 'F') {
SS7_DEBUG_CHAN(ftdmchan, "Received the end of pulsing character %s\n", "");
@@ -551,7 +618,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
} else {
/* if we are coming from idle state then we have already been here once before */
if (ftdmchan->last_state != FTDM_CHANNEL_STATE_IDLE) {
SS7_INFO_CHAN(ftdmchan,"Received %d out of %d so far: %s...starting T35\n",
SS7_INFO_CHAN(ftdmchan, "Received %d out of %d so far: %s...starting T35\n",
i,
sngss7_info->circuit->min_digits,
ftdmchan->caller_data.dnis.digits);
@@ -566,7 +633,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
SS7_ERROR ("Unable to schedule timer, hanging up call!\n");
ftdmchan->caller_data.hangup_cause = 41;
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE;
/* set the flag to indicate this hangup is started from the local side */
sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL);
@@ -574,9 +641,29 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* end the call */
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
} /* if (ftdm_sched_timer(sngss7_info->t35.sched, */
} /* if (ftdmchan->last_state != FTDM_CHANNEL_STATE_IDLE) */
} /* checking ST/#digits */
}
}
/* start ISUP t10 */
if (ftdm_sched_timer (sngss7_info->t10.sched,
"t10",
sngss7_info->t10.beat,
sngss7_info->t10.callback,
&sngss7_info->t10,
&sngss7_info->t10.hb_timer_id)) {
SS7_ERROR ("Unable to schedule timer, hanging up call!\n");
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE;
/* set the flag to indicate this hangup is started from the local side */
sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL);
/* end the call */
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
}
}
break;
@@ -656,10 +743,14 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
/* inform the user there is media avai */
sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_PROGRESS_MEDIA);
} else {
if (!sngss7_test_ckt_flag(sngss7_info, FLAG_SENT_ACM)) {
sngss7_set_ckt_flag(sngss7_info, FLAG_SENT_ACM);
ft_to_sngss7_acm(ftdmchan);
}
ft_to_sngss7_cpg(ftdmchan);
}
/* nothing to do at this time */
break;
/**************************************************************************/
case FTDM_CHANNEL_STATE_UP: /*call is accpeted...both incoming and outgoing */
@@ -751,9 +842,18 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
if (sngss7_test_ckt_flag (sngss7_info, FLAG_REMOTE_REL)) {
/* check if this hangup is from a tx RSC */
if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX)) {
/* go to RESTART State until RSCa is received */
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
if (!sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_SENT)) {
ft_to_sngss7_rsc (ftdmchan);
sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_SENT);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
} else if (sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP)) {
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
} else {
/* go to RESTART State until RSCa is received */
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
}
} else {
/* if the hangup is from a rx RSC, rx GRS, or glare don't sent RLC */
if (!(sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_RX)) &&
@@ -844,7 +944,9 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* check if we came from reset (aka we just processed a reset) */
if ((ftdmchan->last_state == FTDM_CHANNEL_STATE_RESTART) ||
(ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED)) {
(ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) ||
(ftdmchan->last_state == FTDM_CHANNEL_STATE_HANGUP_COMPLETE)) {
/* check if reset flags are up indicating there is more processing to do yet */
if (!(sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX)) &&
@@ -949,9 +1051,12 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
if ((sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX)) &&
!(sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_SENT))) {
/* send a reset request */
ft_to_sngss7_rsc (ftdmchan);
sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_SENT);
/* don't send out reset before finished hanging up if I'm in-use. */
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) {
/* send a reset request */
ft_to_sngss7_rsc (ftdmchan);
sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_SENT);
}
} /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX)) */
@@ -1102,16 +1207,97 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* clear the unblock flag */
sngss7_clear_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX);
/* bring the sig status up */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
/* not bring the cic up if there is a hardware block */
if( !sngss7_test_ckt_blk_flag(sngss7_info, (FLAG_GRP_HW_BLOCK_TX | FLAG_GRP_HW_BLOCK_TX_DN) ) ) {
/* bring the sig status up */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
/* send a uba */
ft_to_sngss7_uba (ftdmchan);
/* send a uba */
ft_to_sngss7_uba (ftdmchan);
}
/* check the last state and return to it to allow the call to finish */
goto suspend_goto_last;
}
/**********************************************************************/
/* hardware block/unblock tx */
if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_GRP_HW_BLOCK_TX ) &&
!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX_DN )) {
SS7_DEBUG_CHAN(ftdmchan, "Processing FLAG_GRP_HW_BLOCK_TX flag %s\n", "");
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN);
/* dont send block again if the channel is already blocked by maintenance */
if( !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX) &&
!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX_DN)
) {
ft_to_sngss7_blo(ftdmchan);
}
sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX_DN);
goto suspend_goto_last;
}
if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_UNBLK_TX)) {
SS7_DEBUG_CHAN(ftdmchan, "Processing FLAG_GRP_HW_UNBLK_TX flag %s\n", "");
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX_DN);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_UNBLK_TX);
/* do not set the channel up if it's blocked by blo/cgb command OR blocked by receiving blo/cgb */
if (!sngss7_test_ckt_blk_flag(sngss7_info, ( FLAG_CKT_MN_BLOCK_TX
| FLAG_CKT_MN_BLOCK_TX
| FLAG_GRP_MN_BLOCK_TX
| FLAG_GRP_MN_BLOCK_TX_DN
| FLAG_CKT_MN_BLOCK_RX
| FLAG_CKT_MN_BLOCK_RX_DN
| FLAG_GRP_MN_BLOCK_RX
| FLAG_GRP_MN_BLOCK_RX_DN
)
)
) {
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
ft_to_sngss7_ubl(ftdmchan);
}
goto suspend_goto_last;
}
#if 0
//jz: there is no such thing of "remote hw block". for receiver, there are only block and unblock
/**********************************************************************/
// jz: hardware block/unblock rx
if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_GRP_HW_BLOCK_RX ) &&
!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX_DN )) {
SS7_DEBUG_CHAN(ftdmchan, "Processing FLAG_GRP_HW_BLOCK_RX flag %s\n", "");
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN);
ft_to_sngss7_bla(ftdmchan);
sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX_DN);
goto suspend_goto_last;
}
if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_GRP_HW_UNBLK_RX )){
SS7_DEBUG_CHAN(ftdmchan, "Processing FLAG_GRP_HW_UNBLK_RX flag %s\n", "");
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX_DN);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_UNBLK_RX);
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
ft_to_sngss7_uba(ftdmchan);
goto suspend_goto_last;
}
#endif
/**********************************************************************/
if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX) &&
!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX_DN)) {
@@ -1142,11 +1328,14 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* clear the unblock flag */
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX);
/* bring the sig status up */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
/* not bring the cic up if there is a hardware block */
if (!sngss7_test_ckt_blk_flag(sngss7_info, (FLAG_GRP_HW_BLOCK_TX | FLAG_GRP_HW_BLOCK_TX_DN))) {
/* bring the sig status up */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
/* send a ubl */
ft_to_sngss7_ubl (ftdmchan);
/* send a ubl */
ft_to_sngss7_ubl(ftdmchan);
}
/* check the last state and return to it to allow the call to finish */
goto suspend_goto_last;
@@ -1624,32 +1813,37 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_ss7_unload)
ftdm_log (FTDM_LOG_INFO, "Starting ftmod_sangoma_ss7 unload...\n");
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_STARTED)) {
sng_isup_free_cc();
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC);
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_STARTED);
}
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_STARTED)) {
ftmod_ss7_shutdown_isup();
sng_isup_free_isup();
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP);
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_STARTED);
}
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3_STARTED)) {
ftmod_ss7_shutdown_mtp3();
sng_isup_free_mtp3();
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3);
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3_STARTED);
}
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_STARTED)) {
ftmod_ss7_shutdown_mtp2();
sng_isup_free_mtp2();
sng_isup_free_mtp1();
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2);
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_STARTED);
}
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY)) {
/* go through all the relays channels and configure it */
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP1_STARTED)) {
sng_isup_free_mtp1();
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP1_STARTED);
}
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY_STARTED)) {
/* go through all the relays channels and disable them */
x = 1;
while (x < (MAX_RELAY_CHANNELS)) {
/* check if this relay channel has been configured already */
@@ -1658,24 +1852,28 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_ss7_unload)
/* send the specific configuration */
if (ftmod_ss7_disable_relay_channel(x)) {
SS7_CRITICAL("Relay Channel %d disable failed!\n", x);
return 1;
/* jz: dont leave like this
* return 1;
* */
} else {
SS7_INFO("Relay Channel %d disable DONE!\n", x);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.relay[x].flags &= !SNGSS7_CONFIGURED;
g_ftdm_sngss7_data.cfg.relay[x].flags &= ~(SNGSS7_CONFIGURED);
} /* if !SNGSS7_CONFIGURED */
x++;
} /* while (x < (MAX_RELAY_CHANNELS)) */
ftmod_ss7_shutdown_relay();
sng_isup_free_relay();
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY);
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY_STARTED);
}
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM_STARTED)) {
sng_isup_free_sm();
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM_STARTED);
}
sng_isup_free_gen();
@@ -51,7 +51,7 @@
/* DEFINES ********************************************************************/
#define MAX_NAME_LEN 25
#define MAX_PATH 255
#define MAX_PATH 4096
#define MAX_CIC_LENGTH 5
#define MAX_CIC_MAP_LENGTH 1000
@@ -64,12 +64,10 @@
(switchtype == LSI_SW_ANS92) || \
(switchtype == LSI_SW_ANS95)
typedef struct ftdm2trillium
{
typedef struct ftdm2trillium {
uint8_t ftdm_val;
uint8_t trillium_val;
}ftdm2trillium_t;
} ftdm2trillium_t;
typedef enum {
SNGSS7_CON_IND_EVENT = 0,
@@ -290,7 +288,6 @@ typedef struct sng_isup_intf {
uint32_t ssf;
uint32_t isap;
uint16_t t4;
uint32_t t10;
uint32_t t11;
uint32_t t18;
uint32_t t19;
@@ -346,6 +343,7 @@ typedef struct sng_isup_ckt {
uint8_t transparent_iam;
void *obj;
uint16_t t3;
uint32_t t10;
uint16_t t12;
uint16_t t13;
uint16_t t14;
@@ -473,6 +471,7 @@ typedef struct sngss7_chan_data {
void *raw_data; /* send on next sigevent */
sngss7_glare_data_t glare;
sngss7_timer_data_t t35;
sngss7_timer_data_t t10;
sngss7_group_data_t rx_grs;
sngss7_group_data_t rx_gra;
sngss7_group_data_t tx_grs;
@@ -609,22 +608,20 @@ typedef enum {
"TX CKT BLK DN", \
"TX CKT UNBLK", \
"TX CKT UNBLK DN", \
"RX GRP MN BLK", \
"RX GRP MN BLK DN", \
"RX GRP MN UNBLK", \
"RX GRP MN UNBLK DN", \
"TX GRP MN BLK", \
"TX GRP MN BLK DN", \
"TX GRP MN UNBLK", \
"TX GRP MN UNBLK DN", \
"RX GRP HW BLK", \
"RX GRP HW BLK DN", \
"RX GRP HW UNBLK", \
"RX GRP HW UNBLK DN", \
"TX GRP HW BLK", \
"TX GRP HW BLK DN", \
"RX GRP MN BLK", \
"RX GRP MN BLK DN", \
"TX GRP MN BLK", \
"TX GRP MN BLK DN", \
"TX GRP HW UNBLK", \
"TX GRP HW UNBLK DN"
"TX GRP HW UNBLK DN", \
"TX GRP MN UNBLK", \
"TX GRP MN UNBLK DN", \
"RX GRP HW UNBLK", \
"RX GRP HW UNBLK DN"
FTDM_STR2ENUM_P(ftmod_ss7_blk_state2flag, ftmod_ss7_blk_flag2str, sng_ckt_block_flag_t)
/* valid for every cfg array except circuits */
@@ -636,13 +633,25 @@ typedef enum {
} sng_cfg_flag_t;
typedef enum {
SNGSS7_SM = (1 << 0),
SNGSS7_RY = (1 << 1),
SNGSS7_MTP1 = (1 << 2),
SNGSS7_MTP2 = (1 << 3),
SNGSS7_MTP3 = (1 << 4),
SNGSS7_ISUP = (1 << 5),
SNGSS7_CC = (1 << 6)
SNGSS7_SM_STARTED = (1 << 0),
SNGSS7_RY_PRESENT = (1 << 2),
SNGSS7_RY_STARTED = (1 << 3),
SNGSS7_MTP1_PRESENT = (1 << 4),
SNGSS7_MTP1_STARTED = (1 << 5),
SNGSS7_MTP2_PRESENT = (1 << 6),
SNGSS7_MTP2_STARTED = (1 << 7),
SNGSS7_MTP3_PRESENT = (1 << 8),
SNGSS7_MTP3_STARTED = (1 << 9),
SNGSS7_ISUP_PRESENT = (1 << 10),
SNGSS7_ISUP_STARTED = (1 << 11),
SNGSS7_CC_PRESENT = (1 << 12),
SNGSS7_CC_STARTED = (1 << 13),
} sng_task_flag_t;
/******************************************************************************/
@@ -739,6 +748,7 @@ int ftmod_ss7_isup_ckt_sta(uint32_t id, unsigned char *state);
/* in ftmod_sangoma_ss7_out.c */
void ft_to_sngss7_iam(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_acm(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_cpg (ftdm_channel_t *ftdmchan);
void ft_to_sngss7_anm(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_rel(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_rlc(ftdm_channel_t *ftdmchan);
@@ -878,6 +888,7 @@ ftdm_status_t sngss7_add_raw_data(sngss7_chan_data_t *sngss7_info, uint8_t* data
/* in ftmod_sangoma_ss7_timers.c */
void handle_isup_t35(void *userdata);
void handle_isup_t10(void *userdata);
/******************************************************************************/
@@ -1029,13 +1040,12 @@ if (ftdmchan->state == new_state) { \
#define sngss7_set_options(obj, option) ((obj)->options |= (option))
#ifdef SS7_PRODUCTION
# define SS7_ASSERT \
SS7_INFO_CHAN(ftdmchan,"Production Mode, continuing%s\n", "");
#ifdef SMG_RELAY_DBG
#define SS7_RELAY_DBG(a,...) printf(a"\n", ##__VA_ARGS__)
#define SS7_RELAY_DBG_FUN(a) printf(#a"\n")
#else
# define SS7_ASSERT \
SS7_ERROR_CHAN(ftdmchan, "Debugging Mode, ending%s\n", ""); \
*(int*)0=0;
#define SS7_RELAY_DBG(a, ...)
#define SS7_RELAY_DBG_FUN(a)
#endif
/******************************************************************************/
@@ -36,6 +36,8 @@
/******************************************************************************/
/* DEFINES ********************************************************************/
#define SNGSS7_EVNTINFO_IND_INBAND_AVAIL 0x03
/******************************************************************************/
/* GLOBALS ********************************************************************/
@@ -171,6 +173,7 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
acm.optBckCalInd.simpleSegmInd.pres = PRSNT_DEF;
acm.optBckCalInd.mlppUserInd.pres = PRSNT_DEF;
acm.optBckCalInd.usrNetIneractInd.pres = PRSNT_DEF;
acm.optBckCalInd.netExcDelInd.pres = PRSNT_DEF;
} /* if (sngss7_test_options(isup_intf, SNGSS7_ACM_OBCI_BITA)) */
/* send the ACM request to LibSngSS7 */
@@ -187,6 +190,31 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
return;
}
void ft_to_sngss7_cpg (ftdm_channel_t *ftdmchan)
{
SiCnStEvnt cpg;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
memset (&cpg, 0, sizeof (cpg));
cpg.evntInfo.eh.pres = PRSNT_NODEF;
cpg.evntInfo.evntInd.pres = PRSNT_NODEF;
cpg.evntInfo.evntInd.val = SNGSS7_EVNTINFO_IND_INBAND_AVAIL; /* Event Indicator = In-band info is now available */
cpg.evntInfo.evntPresResInd.pres = PRSNT_NODEF;
cpg.evntInfo.evntPresResInd.val = 0; /* Event presentation restricted indicator = no indication */
/* send the CPG request to LibSngSS7 */
sng_cc_con_status (1, sngss7_info->suInstId, sngss7_info->spInstId, sngss7_info->circuit->id, &cpg, PROGRESS);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "[CIC:%d]Tx CPG\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
@@ -49,7 +49,7 @@ ftdm_status_t handle_relay_disconnect(RyMngmt *sta);
static ftdm_status_t reconfig_all_ckts_for_relay(void);
static ftdm_status_t disable_all_ckts_for_relay(void);
static ftdm_status_t block_all_ckts_for_relay(uint32_t procId);
static ftdm_status_t unblock_all_ckts_for_relay(uint32_t procId);
/* static ftdm_status_t unblock_all_ckts_for_relay(uint32_t procId); */
static ftdm_status_t disable_all_sigs_for_relay(uint32_t procId);
static ftdm_status_t disble_all_mtp2_sigs_for_relay(void);
/******************************************************************************/
@@ -59,43 +59,26 @@ ftdm_status_t handle_relay_connect(RyMngmt *sta)
{
sng_relay_t *sng_relay = &g_ftdm_sngss7_data.cfg.relay[sta->t.usta.s.ryUpUsta.id];
/* test if this is the first time the channel comes up */
if (!sngss7_test_flag(sng_relay, SNGSS7_RELAY_INIT)) {
SS7_INFO("Relay Channel %d initial connection UP\n", sng_relay->id);
/* mark the channel as being up */
/* SS7_INFO("Relay Channel %d initial connection UP\n", sng_relay->id); */
sngss7_set_flag(sng_relay, SNGSS7_RELAY_INIT);
} else {
SS7_INFO("Relay Channel %d connection UP\n", sng_relay->id);
/* react based on type of channel */
switch (sng_relay->type) {
/******************************************************************/
case (LRY_CT_TCP_CLIENT):
/* reconfigure all ISUP ckts, since the main system would have lost all configs */
}
SS7_INFO("Relay Channel %d connection UP\n", sng_relay->id);
if (sng_relay->type == LRY_CT_TCP_CLIENT) {
if (!sngss7_test_flag(sng_relay, SNGSS7_RELAY_INIT)) {
if (reconfig_all_ckts_for_relay()) {
SS7_ERROR("Failed to reconfigure ISUP Ckts!\n");
/* we're done....this is very bad! */
}
break;
/******************************************************************/
case (LRY_CT_TCP_SERVER):
/* bring the sig links on the client system back up */
ftmod_ss7_enable_grp_mtp3Link(sta->t.usta.s.ryUpUsta.id);
/* unbloock the ckts on the client system */
unblock_all_ckts_for_relay(sta->t.usta.s.ryUpUsta.id);
break;
/******************************************************************/
default:
break;
/******************************************************************/
} /* switch (g_ftdm_sngss7_data.cfg.relay[sta->t.usta.s.ryUpUsta.id].type) */
} /* intial up? */
return FTDM_SUCCESS;
}
return FTDM_SUCCESS;
} else if (sng_relay->type == LRY_CT_TCP_SERVER) {
ftmod_ss7_enable_grp_mtp3Link(sta->t.usta.s.ryUpUsta.id);
/* unbloock the ckts on the client system */
return FTDM_SUCCESS;
}
return FTDM_FAIL;
}
/******************************************************************************/
@@ -300,7 +283,7 @@ ftdm_status_t disable_all_sigs_for_relay(uint32_t procId)
ftdm_status_t disble_all_mtp2_sigs_for_relay(void)
{
/* check if there is a local mtp2 link*/
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2)) {
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_STARTED)) {
SS7_INFO("Disalbing all mtp2 sig links on local system\n");
ftmod_ss7_disable_grp_mtp2Link(1);
@@ -310,6 +293,7 @@ ftdm_status_t disble_all_mtp2_sigs_for_relay(void)
}
#if 0
/******************************************************************************/
static ftdm_status_t unblock_all_ckts_for_relay(uint32_t procId)
{
@@ -345,6 +329,7 @@ static ftdm_status_t unblock_all_ckts_for_relay(uint32_t procId)
return FTDM_SUCCESS;
}
#endif
/******************************************************************************/
/* For Emacs:
@@ -319,7 +319,7 @@ ftdm_status_t copy_genNmb_from_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb
if (genNmb->nmbQual.pres == PRSNT_NODEF) {
snprintf(val, sizeof(val), "%d", genNmb->nmbQual.val);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number \"number qualifier\" \n", val);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number \"number qualifier\" \"%s\"\n", val);
sngss7_add_var(sngss7_info, "ss7_gn_numqual", val);
}
@@ -2454,7 +2454,7 @@ ftdm_status_t sngss7_save_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt)
goto done;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Compressed IAM size:%d\n", len);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Compressed IAM size:%lu\n", len);
/* Worst case: size will triple after url encode */
url_encoded_iam = ftdm_malloc(3*sizeof(*siConEvnt));
@@ -2468,10 +2468,10 @@ ftdm_status_t sngss7_save_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt)
/* URL encode buffer to that its safe to store it in a string */
ftdm_url_encode((const char*)compressed_iam, url_encoded_iam, len);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IAM variable length:%d\n", strlen(url_encoded_iam));
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IAM variable length:%"FTDM_SIZE_FMT"\n", strlen(url_encoded_iam));
if (strlen(url_encoded_iam) > g_ftdm_sngss7_data.cfg.transparent_iam_max_size) {
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "IAM variable length exceeds max size (len:%d max:%d) \n", strlen(url_encoded_iam), g_ftdm_sngss7_data.cfg.transparent_iam_max_size);
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "IAM variable length exceeds max size (len:%"FTDM_SIZE_FMT" max:%d) \n", strlen(url_encoded_iam), g_ftdm_sngss7_data.cfg.transparent_iam_max_size);
ret_val = FTDM_FAIL;
goto done;
}
@@ -2505,10 +2505,10 @@ ftdm_status_t sngss7_retrieve_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt
url_encoded_iam = ftdm_strdup(val);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IAM variable length:%d\n", strlen(val));
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IAM variable length:%"FTDM_SIZE_FMT"\n", strlen(val));
ftdm_url_decode(url_encoded_iam, &url_encoded_iam_len);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Compressed IAM size:%d\n", url_encoded_iam_len);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Compressed IAM size:%"FTDM_SIZE_FMT"\n", url_encoded_iam_len);
uncompressed_buffer = ftdm_malloc(sizeof(*siConEvnt));
ftdm_assert_return(uncompressed_buffer, FTDM_FAIL, "Failed to allocate buffer for uncompressed buffer\n");
@@ -2520,7 +2520,7 @@ ftdm_status_t sngss7_retrieve_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt
}
if (len != sizeof(*siConEvnt)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Incompatible IAM structure size (expected:%d size:%d)\n", sizeof(*siConEvnt), strlen(uncompressed_buffer));
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Incompatible IAM structure size (expected:%"FTDM_SIZE_FMT" size:%"FTDM_SIZE_FMT")\n", sizeof(*siConEvnt), strlen(uncompressed_buffer));
goto done;
}
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2009, Konrad Hammel <konrad@sangoma.com>
* Copyright (c) 2009, Sangoma Technologies
* Konrad Hammel <konrad@sangoma.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,6 +30,11 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
*
* Moises Silva <moy@sangoma.com>
*
*/
/* INCLUDE ********************************************************************/
@@ -56,25 +62,53 @@ void handle_isup_t35(void *userdata)
ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan;
/* now that we have the right channel...put a lock on it so no-one else can use it */
ftdm_mutex_lock(ftdmchan->mutex);
ftdm_channel_lock(ftdmchan);
/* Q.764 2.2.5 Address incomplete (T35 expiry action is hangup with cause 28 according to Table A.1/Q.764) */
SS7_ERROR("[Call-Control] Timer 35 expired on CIC = %d\n", sngss7_info->circuit->cic);
/* set the flag to indicate this hangup is started from the local side */
sngss7_set_ckt_flag(sngss7_info, FLAG_LOCAL_REL);
/* hang up on timer expiry */
ftdmchan->caller_data.hangup_cause = 28;
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_INVALID_NUMBER_FORMAT;
/* end the call */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
/* kill t10 if active */
if (sngss7_info->t10.hb_timer_id) {
ftdm_sched_cancel_timer (sngss7_info->t10.sched, sngss7_info->t10.hb_timer_id);
}
/*unlock*/
ftdm_mutex_unlock(ftdmchan->mutex);
ftdm_channel_unlock(ftdmchan);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void handle_isup_t10(void *userdata)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_timer_data_t *timer = userdata;
sngss7_chan_data_t *sngss7_info = timer->sngss7_info;
ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan;
ftdm_channel_lock(ftdmchan);
SS7_DEBUG("[Call-Control] Timer 10 expired on CIC = %d\n", sngss7_info->circuit->cic);
/* send the call to the user */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
ftdm_channel_unlock(ftdmchan);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
/******************************************************************************/
/* For Emacs:
* Local Variables:
@@ -62,6 +62,7 @@ sng_switch_type_t sng_switch_type_map[] =
{ 1, "india" , LSI_SW_INDIA , LSI_SW_INDIA },
{ 1, "uk" , LSI_SW_UK , LSI_SW_UK },
{ 1, "russia" , LSI_SW_RUSSIA , LSI_SW_RUSSIA },
{ 1, "china" , LSI_SW_CHINA , LSI_SW_CHINA },
{ 0, "", 0, 0 },
};
@@ -127,6 +128,7 @@ typedef struct sng_ccSpan
uint8_t itx_auto_reply;
uint8_t transparent_iam;
uint32_t t3;
uint32_t t10;
uint32_t t12;
uint32_t t13;
uint32_t t14;
@@ -1570,11 +1572,6 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
sng_isap.t9 = atoi(parm->val);
SS7_DEBUG("Found isup t9 = %d\n",sng_isap.t9);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "isup.t10")) {
/**********************************************************************/
sng_isup.t10 = atoi(parm->val);
SS7_DEBUG("Found isup t10 = %d\n",sng_isup.t10);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "isup.t11")) {
/**********************************************************************/
sng_isup.t11 = atoi(parm->val);
@@ -1965,6 +1962,10 @@ static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span)
/**********************************************************************/
sng_ccSpan.t3 = atoi(parm->val);
SS7_DEBUG("Found isup t3 = %d\n", sng_ccSpan.t3);
} else if (!strcasecmp(parm->var, "isup.t10")) {
/**********************************************************************/
sng_ccSpan.t10 = atoi(parm->val);
SS7_DEBUG("Found isup t10 = %d\n", sng_ccSpan.t10);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "isup.t12")) {
/**********************************************************************/
@@ -2082,7 +2083,7 @@ static int ftmod_ss7_fill_in_relay_channel(sng_relay_t *relay_channel)
relay_channel->port,
relay_channel->procId,
relay_channel->id);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY_PRESENT);
} else {
relay_channel->id = i;
SS7_DEBUG("found existing relay channel on type:%d, hostname:%s, port:%d, procId:%d, id = %d\n",
@@ -2116,7 +2117,7 @@ static int ftmod_ss7_fill_in_mtp1_link(sng_mtp1_link_t *mtp1Link)
/* check if this id value has been used already */
if (g_ftdm_sngss7_data.cfg.mtp1Link[i].id == 0) {
SS7_DEBUG("Found new MTP1 Link: id=%d, name=%s\n", mtp1Link->id, mtp1Link->name);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP1);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP1_PRESENT);
} else {
SS7_DEBUG("Found an existing MTP1 Link: id=%d, name=%s (old name=%s)\n",
mtp1Link->id,
@@ -2142,7 +2143,7 @@ static int ftmod_ss7_fill_in_mtp2_link(sng_mtp2_link_t *mtp2Link)
/* check if this id value has been used already */
if (g_ftdm_sngss7_data.cfg.mtp2Link[i].id == 0) {
SS7_DEBUG("Found new MTP2 Link: id=%d, name=%s\n", mtp2Link->id, mtp2Link->name);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2_PRESENT);
} else {
SS7_DEBUG("Found an existing MTP2 Link: id=%d, name=%s (old name=%s)\n",
mtp2Link->id,
@@ -2219,7 +2220,7 @@ static int ftmod_ss7_fill_in_mtp3_link(sng_mtp3_link_t *mtp3Link)
/* check if this id value has been used already */
if (g_ftdm_sngss7_data.cfg.mtp3Link[i].id == 0) {
SS7_DEBUG("Found new MTP3 Link: id=%d, name=%s\n", mtp3Link->id, mtp3Link->name);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3_PRESENT);
} else {
SS7_DEBUG("Found an existing MTP3 Link: id=%d, name=%s (old name=%s)\n",
mtp3Link->id,
@@ -2560,7 +2561,7 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
/* check if this id value has been used already */
if (g_ftdm_sngss7_data.cfg.isupIntf[i].id == 0) {
SS7_DEBUG("Found new ISUP Interface: id=%d, name=%s\n", sng_isup->id, sng_isup->name);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_PRESENT);
} else {
SS7_DEBUG("Found an existing ISUP Interface: id=%d, name=%s (old name=%s)\n",
sng_isup->id,
@@ -2584,11 +2585,6 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
} else {
g_ftdm_sngss7_data.cfg.isupIntf[i].t4 = 3000;
}
if (sng_isup->t10 != 0) {
g_ftdm_sngss7_data.cfg.isupIntf[i].t10 = sng_isup->t10;
} else {
g_ftdm_sngss7_data.cfg.isupIntf[i].t10 = 50;
}
if (sng_isup->t11 != 0) {
g_ftdm_sngss7_data.cfg.isupIntf[i].t11 = sng_isup->t11;
} else {
@@ -2908,7 +2904,7 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
g_ftdm_sngss7_data.cfg.isupCkt[x].type = SNG_CKT_VOICE;
/* throw the flag to indicate that we need to start call control */
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC);
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_PRESENT);
}
if (timeslot.channel) {
@@ -2935,6 +2931,11 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
} else {
g_ftdm_sngss7_data.cfg.isupCkt[x].t3 = ccSpan->t3;
}
if (ccSpan->t10 == 0) {
g_ftdm_sngss7_data.cfg.isupCkt[x].t10 = 50;
} else {
g_ftdm_sngss7_data.cfg.isupCkt[x].t10 = ccSpan->t10;
}
if (ccSpan->t12 == 0) {
g_ftdm_sngss7_data.cfg.isupCkt[x].t12 = 300;
} else {
@@ -2966,9 +2967,10 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
g_ftdm_sngss7_data.cfg.isupCkt[x].t17 = ccSpan->t17;
}
if (ccSpan->t35 == 0) {
g_ftdm_sngss7_data.cfg.isupCkt[x].t17 = 170;
/* Q.764 2.2.5 Address incomplete (T35 is 15-20 seconds according to Table A.1/Q.764) */
g_ftdm_sngss7_data.cfg.isupCkt[x].t35 = 170;
} else {
g_ftdm_sngss7_data.cfg.isupCkt[x].t17 = ccSpan->t35;
g_ftdm_sngss7_data.cfg.isupCkt[x].t35 = ccSpan->t35;
}
if (ccSpan->tval == 0) {
g_ftdm_sngss7_data.cfg.isupCkt[x].tval = 10;
@@ -3062,12 +3064,18 @@ static int ftmod_ss7_fill_in_circuits(sng_span_t *sngSpan)
ftdmchan->call_data = ss7_info;
/* prepare the timer structures */
ss7_info->t35.sched = ((sngss7_span_data_t *)(ftdmspan->signal_data))->sched;
ss7_info->t35.sched = ((sngss7_span_data_t *)(ftdmspan->signal_data))->sched;
ss7_info->t35.counter = 1;
ss7_info->t35.beat = (isupCkt->t35) * 100; /* beat is in ms, t35 is in 100ms */
ss7_info->t35.beat = (isupCkt->t35) * 100; /* beat is in ms, t35 is in 100ms */
ss7_info->t35.callback = handle_isup_t35;
ss7_info->t35.sngss7_info = ss7_info;
ss7_info->t10.sched = ((sngss7_span_data_t *)(ftdmspan->signal_data))->sched;
ss7_info->t10.counter = 1;
ss7_info->t10.beat = (isupCkt->t10) * 100; /* beat is in ms, t10 is in 100ms */
ss7_info->t10.callback = handle_isup_t10;
ss7_info->t10.sngss7_info = ss7_info;
/**************************************************************************/
} /* for (i == 1; i < ftdmspan->chan_count; i++) */
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
+45 -19
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,9 +36,9 @@
* David Yat Sin <davidy@sangoma.com>
* Nenad Corbic <ncorbic@sangoma.com>
* Arnaldo Pereira <arnaldo@sangoma.com>
* Gideon Sadan <gsadan@sangoma.com>
*
*/
*/
#ifdef WP_DEBUG_IO
#define _BSD_SOURCE
#include <syscall.h>
@@ -121,6 +121,16 @@ FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event);
FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event);
FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event);
static void wp_swap16(char *data, int datalen)
{
int i = 0;
uint16_t *samples = (uint16_t *)data;
for (i = 0; i < datalen/2; i++) {
uint16_t sample = ((samples[i] & 0x00FF) << 8) | ((samples[i] & 0xFF00) >> 8);
samples[i] = sample;
}
}
/**
* \brief Poll for event on a wanpipe socket
* \param fd Wanpipe socket descriptor
@@ -305,11 +315,20 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
err = sangoma_tdm_get_hw_coding(chan->sockfd, &tdm_api);
if (tdm_api.wp_tdm_cmd.hw_tdm_coding) {
chan->native_codec = chan->effective_codec = FTDM_CODEC_ALAW;
} else {
chan->native_codec = chan->effective_codec = FTDM_CODEC_ULAW;
}
if ((span->trunk_type == FTDM_TRUNK_GSM) && (chan->type == FTDM_CHAN_TYPE_B)) {
chan->native_codec = FTDM_CODEC_SLIN;
chan->native_interval = 20;
chan->packet_len = 320;
}
err = sangoma_tdm_get_hw_dtmf(chan->sockfd, &tdm_api);
if (err > 0) {
@@ -580,8 +599,9 @@ static FIO_OPEN_FUNCTION(wanpipe_open)
ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL);
ftdmchan->effective_interval = ftdmchan->native_interval = wp_globals.codec_ms;
ftdmchan->packet_len = ftdmchan->native_interval * 8;
/* The packet len will depend on the codec and interval */
ftdmchan->packet_len = ftdmchan->native_interval * ((ftdmchan->native_codec==FTDM_CODEC_SLIN) ? 16 : 8);
if (wp_globals.txqueue_size > 0) {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &wp_globals.txqueue_size);
}
@@ -772,6 +792,7 @@ static FIO_COMMAND_FUNCTION(wanpipe_command)
case FTDM_COMMAND_SET_INTERVAL:
{
err=sangoma_tdm_set_usr_period(ftdmchan->sockfd, &tdm_api, FTDM_COMMAND_OBJ_INT);
ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8);
}
break;
@@ -793,7 +814,7 @@ static FIO_COMMAND_FUNCTION(wanpipe_command)
FTDM_COMMAND_OBJ_INT = wanpipe_swap_bits(rbsbits);
}
#else
// does sangoma_tdm_read_rbs is available here?
/* is sangoma_tdm_read_rbs available here? */
FTDM_COMMAND_OBJ_INT = ftdmchan->rx_cas_bits;
#endif
}
@@ -885,17 +906,11 @@ static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *t
}
if (ftdmchan->iostats.tx.idle_packets < tx_stats->wp_api_tx_hdr_tx_idle_packets) {
/* HDLC channels do not always transmit, so its ok for drivers to fill with idle
* also do not report idle warning when we just started transmitting */
if (ftdmchan->iostats.tx.packets && FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Tx idle changed from %d to %d\n",
ftdmchan->iostats.tx.idle_packets, tx_stats->wp_api_tx_hdr_tx_idle_packets);
}
ftdmchan->iostats.tx.idle_packets = tx_stats->wp_api_tx_hdr_tx_idle_packets;
}
if (!ftdmchan->iostats.tx.packets) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet write stats: Tx queue len: %d, Tx queue size: %d, Tx idle: %d\n",
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet write stats: Tx queue len: %d, Tx queue size: %d, Tx idle: %"FTDM_UINT64_FMT"\n",
ftdmchan->iostats.tx.queue_len,
ftdmchan->iostats.tx.queue_size,
ftdmchan->iostats.tx.idle_packets);
@@ -941,11 +956,11 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx
}
if (ftdmchan->iostats.rx.queue_len >= (0.8 * ftdmchan->iostats.rx.queue_size)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Rx Queue length exceeded 80% threshold (%d/%d)\n",
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Rx Queue length exceeded 80%% threshold (%d/%d)\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
} else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Rx Queue length reduced 80% threshold (%d/%d)\n",
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Rx Queue length reduced 80%% threshold (%d/%d)\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
}
@@ -975,12 +990,15 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx
* \param datalen Size of data buffer
* \return Success, failure or timeout
*/
static FIO_READ_FUNCTION(wanpipe_read)
{
int rx_len = 0;
int rq_len = (int)*datalen;
wp_tdm_api_rx_hdr_t hdrframe;
#ifdef WP_DEBUG_IO
wp_channel_t *wchan = ftdmchan->io_data;
ftdm_time_t time_diff = 0;
@@ -1040,6 +1058,10 @@ static FIO_READ_FUNCTION(wanpipe_read)
wanpipe_read_stats(ftdmchan, &hdrframe);
}
if ((ftdmchan->type == FTDM_CHAN_TYPE_B) && (ftdmchan->span->trunk_type == FTDM_TRUNK_GSM)) {
wp_swap16(data, *datalen);
}
return FTDM_SUCCESS;
}
@@ -1056,6 +1078,10 @@ static FIO_WRITE_FUNCTION(wanpipe_write)
int err = 0;
wp_tdm_api_tx_hdr_t hdrframe;
if ((ftdmchan->type == FTDM_CHAN_TYPE_B) && (ftdmchan->span->trunk_type == FTDM_TRUNK_GSM)) {
wp_swap16(data, *datalen);
}
/* Do we even need the headerframe here? on windows, we don't even pass it to the driver */
memset(&hdrframe, 0, sizeof(hdrframe));
if (*datalen == 0) {
@@ -1490,10 +1516,10 @@ static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fc
if (fchan->dtmfdetect.duration_ms) {
ftdm_time_t diff = ftdm_current_time_in_ms() - fchan->dtmfdetect.start_time;
if (diff > fchan->dtmfdetect.duration_ms) {
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Queuing wanpipe DTMF: %c (duration:%d min:%d)\n", tmp_dtmf[0], diff, fchan->dtmfdetect.duration_ms);
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Queuing wanpipe DTMF: %c (duration:%"FTDM_TIME_FMT" min:%d)\n", tmp_dtmf[0], diff, fchan->dtmfdetect.duration_ms);
ftdm_channel_queue_dtmf(fchan, tmp_dtmf);
} else {
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Ignoring wanpipe DTMF: %c (duration:%d min:%d)\n", tmp_dtmf[0], diff, fchan->dtmfdetect.duration_ms);
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Ignoring wanpipe DTMF: %c (duration:%"FTDM_TIME_FMT" min:%d)\n", tmp_dtmf[0], diff, fchan->dtmfdetect.duration_ms);
}
} else if (!fchan->dtmfdetect.trigger_on_start) {
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Queuing wanpipe DTMF: %c\n", tmp_dtmf[0]);
@@ -1591,7 +1617,7 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
ftdm_clear_flag_locked(span->channels[i], FTDM_CHANNEL_FLASH);
ftdm_set_flag_locked(span->channels[i], FTDM_CHANNEL_OFFHOOK);
event_id = FTDM_OOB_OFFHOOK;
ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "Diff since last event = %llums, delivering %s now\n", diff, ftdm_oob_event2str(event_id));
ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "Diff since last event = %"FTDM_TIME_FMT" ms, delivering %s now\n", diff, ftdm_oob_event2str(event_id));
goto event;
}
}
@@ -1610,7 +1636,7 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
sangoma_tdm_txsig_onhook(ftdmchan->sockfd,&tdm_api);
}
ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "Diff since last event = %llums, delivering %s now\n", diff, ftdm_oob_event2str(event_id));
ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "Diff since last event = %"FTDM_TIME_FMT" ms, delivering %s now\n", diff, ftdm_oob_event2str(event_id));
goto event;
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
+100 -12
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -62,6 +62,9 @@
/*! \brief Max number of groups */
#define FTDM_MAX_GROUPS_INTERFACE FTDM_MAX_SPANS_INTERFACE
/*! \brief Max number of key=value pairs to be sent as signaling stack parameters */
#define FTDM_MAX_SIG_PARAMETERS 30
#define FTDM_INVALID_INT_PARM 0xFF
/*! \brief Thread/Mutex OS abstraction API. */
@@ -201,10 +204,19 @@ FTDM_STR2ENUM_P(ftdm_str2ftdm_chan_type, ftdm_chan_type2str, ftdm_chan_type_t)
(fchan)->span->trunk_type == FTDM_TRUNK_BRI || \
(fchan)->span->trunk_type == FTDM_TRUNK_BRI_PTMP)
/*! \brief Test if a span is digital */
#define FTDM_SPAN_IS_DIGITAL(span) \
((span)->trunk_type == FTDM_TRUNK_E1 || \
(span)->trunk_type == FTDM_TRUNK_T1 || \
(span)->trunk_type == FTDM_TRUNK_J1 || \
(span)->trunk_type == FTDM_TRUNK_BRI || \
(span)->trunk_type == FTDM_TRUNK_BRI_PTMP)
/*! \brief Logging function prototype to be used for all FreeTDM logs
* you should use ftdm_global_set_logger to set your own logger
*/
typedef void (*ftdm_logger_t)(const char *file, const char *func, int line, int level, const char *fmt, ...);
typedef void (*ftdm_logger_t)(const char *file, const char *func, int line, int level, const char *fmt, ...) __ftdm_check_printf(5, 6);
/*! \brief Data queue operation functions
* you can use ftdm_global_set_queue_handler if you want to override the default implementation (not recommended)
@@ -343,6 +355,11 @@ typedef struct {
uint8_t plan;
} ftdm_number_t;
typedef struct {
char from[FTDM_MAX_NUMBER_STR_SZ];
char body[FTDM_MAX_NAME_STR_SZ];
} ftdm_sms_data_t;
/*! \brief Caller information */
typedef struct ftdm_caller_data {
char cid_date[8]; /*!< Caller ID date */
@@ -362,6 +379,7 @@ typedef struct ftdm_caller_data {
/* user information layer 1 protocol */
ftdm_user_layer1_prot_t bearer_layer1;
ftdm_calling_party_category_t cpc; /*!< Calling party category */
uint32_t call_reference;
ftdm_channel_t *fchan; /*!< FreeTDM channel associated (can be NULL) */
@@ -452,12 +470,13 @@ typedef enum {
FTDM_SIGEVENT_INDICATION_COMPLETED, /*!< Last requested indication was completed */
FTDM_SIGEVENT_DIALING, /*!< Outgoing call just started */
FTDM_SIGEVENT_TRANSFER_COMPLETED, /*!< Transfer request is completed */
FTDM_SIGEVENT_SMS,
FTDM_SIGEVENT_INVALID, /*!<Invalid */
} ftdm_signal_event_t;
#define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROCEED", "RINGING", "PROGRESS", \
"PROGRESS_MEDIA", "ALARM_TRAP", "ALARM_CLEAR", \
"COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "FACILITY", \
"TRACE", "TRACE_RAW", "INDICATION_COMPLETED", "DIALING", "TRANSFER_COMPLETED", "INVALID"
"TRACE", "TRACE_RAW", "INDICATION_COMPLETED", "DIALING", "TRANSFER_COMPLETED", "SMS", "INVALID"
/*! \brief Move from string to ftdm_signal_event_t and viceversa */
FTDM_STR2ENUM_P(ftdm_str2ftdm_signal_event, ftdm_signal_event2str, ftdm_signal_event_t)
@@ -471,13 +490,26 @@ typedef enum {
FTDM_TRUNK_FXO,
FTDM_TRUNK_FXS,
FTDM_TRUNK_EM,
FTDM_TRUNK_GSM,
FTDM_TRUNK_NONE
} ftdm_trunk_type_t;
#define TRUNK_STRINGS "E1", "T1", "J1", "BRI", "BRI_PTMP", "FXO", "FXS", "EM", "NONE"
#define TRUNK_TYPE_STRINGS "E1", "T1", "J1", "BRI", "BRI_PTMP", "FXO", "FXS", "EM", "GSM", "NONE"
/*! \brief Move from string to ftdm_trunk_type_t and viceversa */
FTDM_STR2ENUM_P(ftdm_str2ftdm_trunk_type, ftdm_trunk_type2str, ftdm_trunk_type_t)
/*! \brief Span trunk modes */
typedef enum {
FTDM_TRUNK_MODE_CPE,
FTDM_TRUNK_MODE_NET,
FTDM_TRUNK_MODE_INVALID
} ftdm_trunk_mode_t;
#define TRUNK_MODE_STRINGS "CPE", "NET", "INVALID"
/*! \brief Move from string to ftdm_trunk_mode_t and viceversa */
FTDM_STR2ENUM_P(ftdm_str2ftdm_trunk_mode, ftdm_trunk_mode2str, ftdm_trunk_mode_t)
/*! \brief Basic channel configuration provided to ftdm_configure_span_channels */
typedef struct ftdm_channel_config {
char name[FTDM_MAX_NAME_STR_SZ];
@@ -621,14 +653,6 @@ typedef enum {
FTDM_CRASH_ON_ASSERT
} ftdm_crash_policy_t;
/*! \brief I/O waiting flags */
typedef enum {
FTDM_NO_FLAGS = 0,
FTDM_READ = (1 << 0),
FTDM_WRITE = (1 << 1),
FTDM_EVENTS = (1 << 2)
} ftdm_wait_flag_t;
/*! \brief Signaling configuration parameter for the stacks (variable=value pair) */
typedef struct ftdm_conf_parameter {
const char *var;
@@ -783,6 +807,8 @@ struct ftdm_memory_handler {
#define FIO_CONFIGURE_SPAN_SIGNALING_ARGS (ftdm_span_t *span, fio_signal_cb_t sig_cb, ftdm_conf_parameter_t *ftdm_parameters)
#define FIO_SIG_UNLOAD_ARGS (void)
#define FIO_API_ARGS (ftdm_stream_handle_t *stream, const char *data)
#define FIO_SPAN_START_ARGS (ftdm_span_t *span)
#define FIO_SPAN_STOP_ARGS (ftdm_span_t *span)
/*! \brief FreeTDM I/O layer interface function typedefs
* You don't need these unless your implementing an I/O interface module (most users don't) */
@@ -829,6 +855,8 @@ typedef ftdm_status_t (*fio_configure_span_signaling_t) FIO_CONFIGURE_SPAN_SIGNA
typedef ftdm_status_t (*fio_io_unload_t) FIO_IO_UNLOAD_ARGS ;
typedef ftdm_status_t (*fio_sig_unload_t) FIO_SIG_UNLOAD_ARGS ;
typedef ftdm_status_t (*fio_api_t) FIO_API_ARGS ;
typedef ftdm_status_t (*fio_span_start_t) FIO_SPAN_START_ARGS ;
typedef ftdm_status_t (*fio_span_stop_t) FIO_SPAN_STOP_ARGS ;
/*! \brief FreeTDM I/O layer interface function prototype wrapper macros
@@ -863,6 +891,8 @@ typedef ftdm_status_t (*fio_api_t) FIO_API_ARGS ;
#define FIO_IO_UNLOAD_FUNCTION(name) ftdm_status_t name FIO_IO_UNLOAD_ARGS
#define FIO_SIG_UNLOAD_FUNCTION(name) ftdm_status_t name FIO_SIG_UNLOAD_ARGS
#define FIO_API_FUNCTION(name) ftdm_status_t name FIO_API_ARGS
#define FIO_SPAN_START_FUNCTION(name) ftdm_status_t name FIO_SPAN_START_ARGS
#define FIO_SPAN_STOP_FUNCTION(name) ftdm_status_t name FIO_SPAN_STOP_ARGS
/*! \brief FreeTDM I/O layer function prototype wrapper macros
* You don't need these unless your implementing an I/O interface module (most users don't) */
@@ -883,6 +913,8 @@ struct ftdm_io_interface {
fio_span_next_event_t next_event; /*!< Retrieve an event from the span */
fio_channel_next_event_t channel_next_event; /*!< Retrieve an event from channel */
fio_api_t api; /*!< Execute a text command */
fio_span_start_t span_start; /*!< Start span I/O */
fio_span_stop_t span_stop; /*!< Stop span I/O */
};
/*! \brief FreeTDM supported I/O codecs */
@@ -1741,6 +1773,28 @@ FT_DECLARE(ftdm_trunk_type_t) ftdm_span_get_trunk_type(const ftdm_span_t *span);
/*! \brief For display debugging purposes you can display this string which describes the trunk type of a span */
FT_DECLARE(const char *) ftdm_span_get_trunk_type_str(const ftdm_span_t *span);
/*!
* Set the trunk mode for a span
* \note This must be called before configuring any channels within the span!
* \param[in] span The span
* \param[in] type The trunk mode
*/
FT_DECLARE(void) ftdm_span_set_trunk_mode(ftdm_span_t *span, ftdm_trunk_mode_t mode);
/*!
* Get the trunk mode for a span
* \param[in] span The span
* \return Span trunk mode
*/
FT_DECLARE(ftdm_trunk_mode_t) ftdm_span_get_trunk_mode(const ftdm_span_t *span);
/*!
* Get the trunk mode of a span in textual form
* \param[in] span The span
* \return Span mode name as a string
*/
FT_DECLARE(const char *) ftdm_span_get_trunk_mode_str(const ftdm_span_t *span);
/*!
* \brief Return the channel identified by the provided id
*
@@ -1811,6 +1865,40 @@ 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);
/**
* Generate a stack trace and invoke a callback function for each entry
* \param[in] callback Callback function, that is invoked for each stack symbol
* \param[in] priv (User-)Private data passed to the callback
* \retval
* FTDM_SUCCESS On success
* FTDM_NOTIMPL Backtraces are not available
* FTDM_EINVAL Invalid arguments (callback was NULL)
*/
FT_DECLARE(ftdm_status_t) ftdm_backtrace_walk(void (* callback)(const int tid, const void *addr, const char *symbol, void *priv), void *priv);
/**
* Convenience function to print a backtrace for a span.
* \note The backtrace is generated with FTDM_LOG_DEBUG log level.
* \param[in] span Span object
* \retval
* FTDM_SUCCESS On success
* FTDM_NOTIMPL Backtraces are not available
* FTDM_EINVAL Invalid arguments (e.g. span was NULL)
*/
FT_DECLARE(ftdm_status_t) ftdm_backtrace_span(ftdm_span_t *span);
/**
* Convenience function to print a backtrace for a channel.
* \note The backtrace is generated with FTDM_LOG_DEBUG log level.
* \param[in] chan Channel object
* \retval
* FTDM_SUCCESS On success
* FTDM_NOTIMPL Backtraces are not available
* FTDM_EINVAL Invalid arguments (e.g. chan was NULL)
*/
FT_DECLARE(ftdm_status_t) ftdm_backtrace_chan(ftdm_channel_t *chan);
FT_DECLARE_DATA extern ftdm_logger_t ftdm_log;
/*! \brief Basic transcoding function prototype */
+50
View File
@@ -121,6 +121,36 @@ extern "C" {
#pragma comment(lib, "Winmm")
#endif
/*
* Compiler-specific format checking attributes
* use these on custom functions that use printf/scanf-style
* format strings (e.g. ftdm_log())
*/
#if defined(__GNUC__)
/**
* Enable compiler-specific printf()-style format and argument checks on a function
* @param fmtp Position of printf()-style format string parameter
* @param argp Position of variable argument list ("...") parameter
* @code
* void log(const int level, const char *fmt, ...) __ftdm_check_printf(2, 3);
* @endcode
*/
#define __ftdm_check_printf(fmtp, argp) __attribute__((format (printf, fmtp, argp)))
/**
* Enable compiler-specific scanf()-style format and argument checks on a function
* @param fmtp Position of scanf()-style format string parameter
* @param argp Position of variable argument list ("...") parameter
* @code
* void parse(struct foo *ctx, const char *fmt, ...) __ftdm_check_scanf(2, 3);
* @endcode
*/
#define __ftdm_check_scanf(fmtp, argp) __attribute__((format (scanf, fmtp, argp)))
#else
#define __ftdm_check_printf(fmtp, argp)
#define __ftdm_check_scanf(fmtp, argp)
#endif
#define FTDM_STR2ENUM_P(_FUNC1, _FUNC2, _TYPE) FT_DECLARE(_TYPE) _FUNC1 (const char *name); FT_DECLARE(const char *) _FUNC2 (_TYPE type);
#define FTDM_STR2ENUM(_FUNC1, _FUNC2, _TYPE, _STRINGS, _MAX) \
FT_DECLARE(_TYPE) _FUNC1 (const char *name) \
@@ -160,6 +190,9 @@ typedef __int16 int16_t;
typedef __int8 int8_t;
#define FTDM_O_BINARY O_BINARY
#define FTDM_SIZE_FMT "Id"
#define FTDM_INT64_FMT "lld"
#define FTDM_UINT64_FMT "llu"
#define FTDM_XINT64_FMT "llx"
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#else
@@ -168,6 +201,15 @@ typedef __int8 int8_t;
#else /* __WINDOWS__ */
#define FTDM_O_BINARY 0
#define FTDM_SIZE_FMT "zd"
#if (defined(__SIZEOF_LONG__) && (__SIZEOF_LONG__ == 8)) || defined(__LP64__) || defined(__LLP64__)
#define FTDM_INT64_FMT "ld"
#define FTDM_UINT64_FMT "lu"
#define FTDM_XINT64_FMT "lx"
#else
#define FTDM_INT64_FMT "lld"
#define FTDM_UINT64_FMT "llu"
#define FTDM_XINT64_FMT "llx"
#endif
#define FTDM_INVALID_SOCKET -1
typedef int ftdm_socket_t;
#include <stdio.h>
@@ -203,6 +245,14 @@ typedef enum {
FTDM_TRUE
} ftdm_bool_t;
/*! \brief I/O waiting flags */
typedef enum {
FTDM_NO_FLAGS = 0,
FTDM_READ = (1 << 0),
FTDM_WRITE = (1 << 1),
FTDM_EVENTS = (1 << 2)
} ftdm_wait_flag_t;
/*!
* \brief FreeTDM channel.
* This is the basic data structure used to place calls and I/O operations
+51
View File
@@ -53,6 +53,8 @@ extern "C" {
/*! \brief time data type */
typedef uint64_t ftdm_time_t;
/*! format string for ftdm_time_t */
#define FTDM_TIME_FMT FTDM_UINT64_FMT
/*! \brief sleep x amount of milliseconds */
#ifdef __WINDOWS__
@@ -76,6 +78,55 @@ typedef uint64_t ftdm_time_t;
/*! \brief array len helper */
#define ftdm_array_len(array) sizeof(array)/sizeof(array[0])
/*! \brief Get smaller value */
#define ftdm_min(x,y) ((x) < (y) ? (x) : (y))
/*! \brief Get larger value */
#define ftdm_max(x,y) ((x) > (y) ? (x) : (y))
/*! \brief Get value that is in range [vmin,vmax] */
#define ftdm_clamp(val,vmin,vmax) ftdm_max(vmin,ftdm_min(val,vmax))
/*!
* \brief Get offset of member in structure
* \param[in] type Type of struct
* \param[in] member Name of struct member
* \code
* struct a {
* int foo;
* int bar;
* };
*
* int offset_a_bar = ftdm_offset_of(struct a, bar); // 4 byte offset
* \endcode
*/
#define ftdm_offset_of(type,member) (uintptr_t)&(((type *)0)->member)
/*!
* \brief Get pointer to enclosing structrure from pointer to embedded member
* \param[in] ptr Pointer to embedded member
* \param[in] type Type of parent/container structure
* \param[in] member Name of embedded member in parent/container struct
* \code
* struct engine {
* int nr_cyl;
* };
*
* struct car {
* char model[10];
* struct engine eng; // struct engine embedded in car(!)
* };
*
* int somefunc(struct engine *e) {
* struct car *c = ftdm_container_of(e, struct car, eng);
*
* ... do something with car ...
* }
* \endcode
*/
#define ftdm_container_of(ptr,type,member) (type *)((uintptr_t)(ptr) - ftdm_offset_of(type, member))
/*! \brief The memory handler.
Do not use directly this variable, use the memory macros and ftdm_global_set_memory_handler to override */
FT_DECLARE_DATA extern ftdm_memory_handler_t g_ftdm_mem_handler;
+2 -1
View File
@@ -52,11 +52,12 @@ FT_DECLARE(ftdm_status_t) _ftdm_mutex_trylock(const char *file, int line, const
#define ftdm_mutex_unlock(_x) _ftdm_mutex_unlock(__FILE__, __LINE__, __FUNCTION__, _x)
FT_DECLARE(ftdm_status_t) _ftdm_mutex_unlock(const char *file, int line, const char *func, ftdm_mutex_t *mutex);
FT_DECLARE(ftdm_status_t) ftdm_interrupt_create(ftdm_interrupt_t **cond, ftdm_socket_t device);
FT_DECLARE(ftdm_status_t) ftdm_interrupt_create(ftdm_interrupt_t **cond, ftdm_socket_t device, ftdm_wait_flag_t device_flags);
FT_DECLARE(ftdm_status_t) ftdm_interrupt_destroy(ftdm_interrupt_t **cond);
FT_DECLARE(ftdm_status_t) ftdm_interrupt_signal(ftdm_interrupt_t *cond);
FT_DECLARE(ftdm_status_t) ftdm_interrupt_wait(ftdm_interrupt_t *cond, int ms);
FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interrupts[], ftdm_size_t size, int ms);
FT_DECLARE(ftdm_wait_flag_t) ftdm_interrupt_device_ready(ftdm_interrupt_t *interrupt);
#ifdef __cplusplus
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
+25 -3
View File
@@ -214,12 +214,33 @@ extern "C" {
ftdm_mutex_lock(obj->mutex); \
} \
if(!__safety) { \
ftdm_log(FTDM_LOG_CRIT, "flag %d was never cleared\n", flag); \
ftdm_log(FTDM_LOG_CRIT, "flag %"FTDM_UINT64_FMT" was never cleared\n", (uint64_t)flag); \
} \
} while(0);
#define ftdm_is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119)
#ifdef __linux__
#define ftdm_print_stack(level) \
do { \
void *__stacktrace[100] = { 0 }; \
char **__symbols = NULL; \
int __size = 0; \
int __i = 0; \
__size = backtrace(__stacktrace, ftdm_array_len(__stacktrace)); \
__symbols = backtrace_symbols(__stacktrace, __size); \
if (__symbols) { \
for (__i = 0; __i < __size; __i++) { \
ftdm_log(__level, "%s\n", __symbols[i]); \
} \
free(__symbols); \
} \
} while (0);
#else
#define ftdm_print_stack(level) ftdm_log(level, "FTDM_PRINT_STACK is not implemented in this operating system!\n");
#endif
#define FTDM_SPAN_IS_BRI(x) ((x)->trunk_type == FTDM_TRUNK_BRI || (x)->trunk_type == FTDM_TRUNK_BRI_PTMP)
/*!
\brief Copy flags from one arbitrary object to another
@@ -464,6 +485,7 @@ struct ftdm_span {
fio_event_cb_t event_callback;
ftdm_mutex_t *mutex;
ftdm_trunk_type_t trunk_type;
ftdm_trunk_mode_t trunk_mode;
ftdm_analog_start_type_t start_type;
ftdm_signal_type_t signal_type;
uint32_t last_used_index;
@@ -673,7 +695,7 @@ FT_DECLARE(ftdm_status_t) ftdm_sigmsg_set_raw_data(ftdm_sigmsg_t *sigmsg, void *
*/
#define ftdm_assert(assertion, msg) \
if (!(assertion)) { \
ftdm_log(FTDM_LOG_CRIT, msg); \
ftdm_log(FTDM_LOG_CRIT, "%s", msg); \
if (g_ftdm_crash_policy & FTDM_CRASH_ON_ASSERT) { \
ftdm_abort(); \
} \
@@ -684,7 +706,7 @@ FT_DECLARE(ftdm_status_t) ftdm_sigmsg_set_raw_data(ftdm_sigmsg_t *sigmsg, void *
*/
#define ftdm_assert_return(assertion, retval, msg) \
if (!(assertion)) { \
ftdm_log(FTDM_LOG_CRIT, msg); \
ftdm_log(FTDM_LOG_CRIT, "%s", msg); \
if (g_ftdm_crash_policy & FTDM_CRASH_ON_ASSERT) { \
ftdm_abort(); \
} else { \
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* Copyright (c) 2007-2012, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -163,7 +163,8 @@ typedef enum {
FTDM_SIGTYPE_SANGOMABOOST,
FTDM_SIGTYPE_M3UA,
FTDM_SIGTYPE_R2,
FTDM_SIGTYPE_SS7
FTDM_SIGTYPE_SS7,
FTDM_SIGTYPE_GSM
} ftdm_signal_type_t;
typedef enum {
@@ -173,6 +174,12 @@ typedef enum {
FTDM_SPAN_SUSPENDED = (1 << 3),
FTDM_SPAN_IN_THREAD = (1 << 4),
FTDM_SPAN_STOP_THREAD = (1 << 5),
/*! Signaling modules set this flag to use fchan->pendingchans queue instead
* of the FTDM_SPAN_STATE_CHANGE flag to detect when there is channels with
* a state change pending in the span. If you set this member you can't rely
* on FTDM_SPAN_STATE_CHANGE anymore and must use the queue only instead. This
* is the new way of detecting state changes, new modules should always set this
* flag, the old modules still relying on FTDM_SPAN_STATE_CHANGE should be updated */
FTDM_SPAN_USE_CHAN_QUEUE = (1 << 6),
FTDM_SPAN_SUGGEST_CHAN_ID = (1 << 7),
FTDM_SPAN_USE_AV_RATE = (1 << 8),
@@ -1,6 +1,6 @@
/*
* libteletone
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -1,6 +1,6 @@
/*
* libteletone
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -1,6 +1,6 @@
/*
* libteletone
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
+1 -1
View File
@@ -4,7 +4,7 @@
* Author(s): Anthony Minessale II <anthm@freeswitch.org>
* Nenad Corbic <ncorbic@sangoma.com>
*
* Copyright: (c) 2005 Anthony Minessale II
* Copyright: (c) 2005-2012 Anthony Minessale II
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
+1 -1
View File
@@ -4,7 +4,7 @@
* Author(s): Anthony Minessale II <anthm@freeswitch.org>
* Nenad Corbic <ncorbic@sangoma.com>
*
* Copyright: (c) 2005 Anthony Minessale II
* Copyright: (c) 2005-2012 Anthony Minessale II
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
+1 -1
View File
@@ -4,7 +4,7 @@
* Author(s): Anthony Minessale II <anthm@freeswitch.org>
* Nenad Corbic <ncorbic@sangoma.com>
*
* Copyright: (c) 2005 Anthony Minessale II
* Copyright: (c) 2005-2012 Anthony Minessale II
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
+1 -1
View File
@@ -144,7 +144,7 @@ int main(int argc, char *argv[])
ftdm_channel_call_indicate(lchan, ind);
stop = ftdm_current_time_in_ms();
diff = stop - start;
ftdm_log(FTDM_LOG_DEBUG, "Setting indication %s took %llums\n",
ftdm_log(FTDM_LOG_DEBUG, "Setting indication %s took %"FTDM_TIME_FMT" ms\n",
ftdm_channel_indication2str(ind), diff);
}
}