Merge root@192.168.1.163:/freeswitch

Conflicts:

	libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c
This commit is contained in:
David Yat Sin committed 2010-04-15 11:54:32 -04:00
commit c4f821f822
26 files changed
+1002 -153

No files matched your search

+238 -8
View File
@@ -91,6 +91,7 @@ static struct {
char hold_music[256];
switch_mutex_t *mutex;
analog_option_t analog_options;
switch_hash_t *ss7_configs;
} globals;
struct private_object {
@@ -1961,6 +1962,15 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
}
static FIO_SIGNAL_CB_FUNCTION(on_ss7_signal)
{
if (on_common_signal(sigmsg) == FTDM_BREAK) {
return FTDM_SUCCESS;
}
ftdm_log(FTDM_LOG_DEBUG, "got ss7 sig %d:%d [%s]\n", sigmsg->channel->span_id, sigmsg->channel->chan_id, ftdm_signal_event2str(sigmsg->event_id));
return FTDM_SUCCESS;
}
static FIO_SIGNAL_CB_FUNCTION(on_analog_signal)
{
switch_status_t status = SWITCH_STATUS_FALSE;
@@ -2022,10 +2032,140 @@ static uint32_t enable_analog_option(const char *str, uint32_t current_options)
}
/* create ftdm_conf_node_t tree based on a fixed pattern XML configuration list
* last 2 args are for limited aka dumb recursivity
* */
static int add_config_list_nodes(switch_xml_t swnode, ftdm_conf_node_t *rootnode,
const char *list_name, const char *list_element_name,
const char *sub_list_name, const char *sub_list_element_name)
{
char *var, *val;
switch_xml_t list;
switch_xml_t element;
switch_xml_t param;
ftdm_conf_node_t *n_list;
ftdm_conf_node_t *n_element;
list = switch_xml_child(swnode, list_name);
if (!list) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no list %s found\n", list_name);
return -1;
}
if ((FTDM_SUCCESS != ftdm_conf_node_create(list_name, &n_list, rootnode))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create %s node\n", list_name);
return -1;
}
for (element = switch_xml_child(list, list_element_name); element; element = element->next) {
char *element_name = (char *) switch_xml_attr(element, "name");
if (!element_name) {
continue;
}
if ((FTDM_SUCCESS != ftdm_conf_node_create(list_element_name, &n_element, n_list))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create %s node for %s\n", list_element_name, element_name);
return -1;
}
ftdm_conf_node_add_param(n_element, "name", element_name);
for (param = switch_xml_child(element, "param"); param; param = param->next) {
var = (char *) switch_xml_attr_soft(param, "name");
val = (char *) switch_xml_attr_soft(param, "value");
ftdm_conf_node_add_param(n_element, var, val);
}
if (sub_list_name && sub_list_element_name) {
if (add_config_list_nodes(element, n_element, sub_list_name, sub_list_element_name, NULL, NULL)) {
return -1;
}
}
}
return 0;
}
static ftdm_conf_node_t *get_ss7_config_node(switch_xml_t cfg, const char *confname)
{
switch_xml_t signode, ss7configs, isup;
ftdm_conf_node_t *rootnode;
/* try to find the conf in the hash first */
rootnode = switch_core_hash_find(globals.ss7_configs, confname);
if (rootnode) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "ss7 config %s was found in the hash already\n", confname);
return rootnode;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "not found %s config in hash, searching in xml ...\n", confname);
signode = switch_xml_child(cfg, "signaling_configs");
if (!signode) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not found 'signaling_configs' XML config section\n");
return NULL;
}
ss7configs = switch_xml_child(signode, "sngss7_configs");
if (!ss7configs) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not found 'sngss7_configs' XML config section\n");
return NULL;
}
/* search the isup config */
for (isup = switch_xml_child(ss7configs, "sng_isup"); isup; isup = isup->next) {
char *name = (char *) switch_xml_attr(isup, "name");
if (!name) {
continue;
}
if (!strcasecmp(name, confname)) {
break;
}
}
if (!isup) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not found '%s' sng_isup XML config section\n", confname);
return NULL;
}
/* found our XML chunk, create the root node */
if ((FTDM_SUCCESS != ftdm_conf_node_create("sng_isup", &rootnode, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create root node for sng_isup config %s\n", confname);
return NULL;
}
/* add mtp linksets */
if (add_config_list_nodes(isup, rootnode, "mtp_linksets", "mtp_linkset", "mtp_links", "mtp_link")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp_linksets for sng_isup config %s\n", confname);
ftdm_conf_node_destroy(rootnode);
return NULL;
}
/* add mtp routes */
if (add_config_list_nodes(isup, rootnode, "mtp_routes", "mtp_route", NULL, NULL)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp_routes for sng_isup config %s\n", confname);
ftdm_conf_node_destroy(rootnode);
return NULL;
}
/* add isup interfaces */
if (add_config_list_nodes(isup, rootnode, "isup_interfaces", "isup_interface", NULL, NULL)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process isup_interfaces for sng_isup config %s\n", confname);
ftdm_conf_node_destroy(rootnode);
return NULL;
}
switch_core_hash_insert(globals.ss7_configs, confname, rootnode);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Added SS7 node configuration %s\n", confname);
return rootnode;
}
static switch_status_t load_config(void)
{
const char *cf = "freetdm.conf";
switch_xml_t cfg, xml, settings, param, spans, myspan;
ftdm_conf_node_t *ss7confnode = NULL;
ftdm_span_t *boost_spans[FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN];
ftdm_span_t *boost_span = NULL;
unsigned boosti = 0;
@@ -2054,6 +2194,91 @@ static switch_status_t load_config(void)
}
}
switch_core_hash_init(&globals.ss7_configs, module_pool);
if ((spans = switch_xml_child(cfg, "ss7_spans"))) {
for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
ftdm_status_t zstatus = FTDM_FAIL;
const char *context = "default";
const char *dialplan = "XML";
ftdm_conf_parameter_t spanparameters[30];
char *id = (char *) switch_xml_attr(myspan, "id");
char *name = (char *) switch_xml_attr(myspan, "name");
char *configname = (char *) switch_xml_attr(myspan, "config");
ftdm_span_t *span = NULL;
uint32_t span_id = 0;
unsigned paramindex = 0;
if (!name && !id) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ss7 span missing required attribute 'id' or 'name', skipping ...\n");
continue;
}
if (!configname) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ss7 span missing required attribute, skipping ...\n");
continue;
}
if (name) {
zstatus = ftdm_span_find_by_name(name, &span);
} else {
if (switch_is_number(id)) {
span_id = atoi(id);
zstatus = ftdm_span_find(span_id, &span);
}
if (zstatus != FTDM_SUCCESS) {
zstatus = ftdm_span_find_by_name(id, &span);
}
}
if (zstatus != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
continue;
}
if (!span_id) {
span_id = span->span_id;
}
ss7confnode = get_ss7_config_node(cfg, configname);
if (!ss7confnode) {
ftdm_log(FTDM_LOG_ERROR, "Error finding ss7config '%s' for FreeTDM span id: %s\n", configname, switch_str_nil(id));
continue;
}
memset(spanparameters, 0, sizeof(spanparameters));
for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if (sizeof(spanparameters)/sizeof(spanparameters[0]) == paramindex) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Too many parameters for ss7 span, ignoring any parameter after %s\n", var);
break;
}
if (!strcasecmp(var, "context")) {
context = val;
} else if (!strcasecmp(var, "dialplan")) {
dialplan = val;
} else {
spanparameters[paramindex].var = var;
spanparameters[paramindex].val = val;
paramindex++;
}
}
if (ftdm_configure_span("ss7", span, on_ss7_signal,
"confnode", ss7confnode,
"parameters", spanparameters,
TAG_END) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error configuring ss7 FreeTDM span %d\n", span_id);
continue;
}
SPAN_CONFIG[span->span_id].span = span;
switch_copy_string(SPAN_CONFIG[span->span_id].context, context, sizeof(SPAN_CONFIG[span->span_id].context));
switch_copy_string(SPAN_CONFIG[span->span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span->span_id].dialplan));
switch_copy_string(SPAN_CONFIG[span->span_id].type, "Sangoma (SS7)", sizeof(SPAN_CONFIG[span->span_id].type));
ftdm_log(FTDM_LOG_DEBUG, "Configured ss7 FreeTDM span %d with config node %s\n", span_id, configname);
}
}
if ((spans = switch_xml_child(cfg, "analog_spans"))) {
for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
char *id = (char *) switch_xml_attr(myspan, "id");
@@ -2504,7 +2729,6 @@ static switch_status_t load_config(void)
const char *dialplan = "XML";
uint32_t span_id = 0;
ftdm_span_t *span = NULL;
const char *tonegroup = NULL;
ftdm_conf_parameter_t spanparameters[30];
unsigned paramindex = 0;
@@ -2526,9 +2750,8 @@ static switch_status_t load_config(void)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Too many parameters for boost span, ignoring any parameter after %s\n", var);
break;
}
if (!strcasecmp(var, "tonegroup")) {
tonegroup = val;
} else if (!strcasecmp(var, "context")) {
if (!strcasecmp(var, "context")) {
context = val;
} else if (!strcasecmp(var, "dialplan")) {
dialplan = val;
@@ -2539,10 +2762,6 @@ static switch_status_t load_config(void)
}
}
if (!tonegroup) {
tonegroup = "us";
}
if (name) {
zstatus = ftdm_span_find_by_name(name, &span);
} else {
@@ -3194,6 +3413,17 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load)
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_freetdm_shutdown)
{
switch_hash_index_t *hi;
const void *var;
void *val;
/* destroy ss7 configs */
for (hi = switch_hash_first(NULL, globals.ss7_configs); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
ftdm_conf_node_destroy(val);
}
ftdm_global_destroy();
// this breaks pika but they are MIA so *shrug*
+80
View File
@@ -29,6 +29,10 @@
* 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 "freetdm.h"
@@ -239,6 +243,82 @@ FT_DECLARE (int) ftdm_config_get_cas_bits(char *strvalue, unsigned char *outbits
return 0;
}
#define PARAMETERS_CHUNK_SIZE 20
FT_DECLARE(ftdm_status_t) ftdm_conf_node_create(const char *name, ftdm_conf_node_t **node, ftdm_conf_node_t *parent)
{
ftdm_conf_node_t *newnode;
ftdm_conf_node_t *sibling = NULL;
ftdm_assert_return(name != NULL, FTDM_FAIL, "null node name");
newnode = ftdm_calloc(1, sizeof(**node));
if (!newnode) {
return FTDM_MEMERR;
}
strncpy(newnode->name, name, sizeof(newnode->name)-1);
newnode->name[sizeof(newnode->name)-1] = 0;
newnode->parameters = ftdm_calloc(PARAMETERS_CHUNK_SIZE, sizeof(*newnode->parameters));
if (!newnode->parameters) {
ftdm_safe_free(newnode);
return FTDM_MEMERR;
}
newnode->t_parameters = PARAMETERS_CHUNK_SIZE;
if (parent) {
/* store who my parent is */
newnode->parent = parent;
/* save any siblings */
sibling = parent->child;
/* as a newborn I am first */
parent->child = newnode;
if (sibling) {
/* store a pointer to my next sibling */
newnode->next = sibling;
}
}
*node = newnode;
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) ftdm_conf_node_add_param(ftdm_conf_node_t *node, const char *param, const char *val)
{
void *newparameters;
ftdm_assert_return(param != NULL, FTDM_FAIL, "param is null");
ftdm_assert_return(val != NULL, FTDM_FAIL, "val is null");
if (node->n_parameters == node->t_parameters) {
newparameters = ftdm_realloc(node->parameters, (node->t_parameters + PARAMETERS_CHUNK_SIZE) * sizeof(*node->parameters));
if (!newparameters) {
return FTDM_MEMERR;
}
node->parameters = newparameters;
node->t_parameters = node->n_parameters + PARAMETERS_CHUNK_SIZE;
}
node->parameters[node->n_parameters].var = param;
node->parameters[node->n_parameters].val = val;
node->n_parameters++;
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) ftdm_conf_node_destroy(ftdm_conf_node_t *node)
{
ftdm_conf_node_t *curr = NULL;
ftdm_conf_node_t *child = node->child;
while (child) {
curr = child;
child = curr->next;
ftdm_conf_node_destroy(curr);
}
ftdm_free(node->parameters);
ftdm_free(node);
return FTDM_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
+14 -9
View File
@@ -1087,16 +1087,20 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(ftdm_channel_t *ftdmchan, ftdm_
}
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
ftdm_log(FTDM_LOG_CRIT, "Ignored state change request from %s to %s, the previous state change has not been processed yet\n",
ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state));
return FTDM_FAIL;
}
if (lock) {
ftdm_mutex_lock(ftdmchan->mutex);
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
ftdm_log(FTDM_LOG_CRIT, "Ignored state change request from %s to %s, the previous state change has not been processed yet\n",
ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state));
if (lock) {
ftdm_mutex_unlock(ftdmchan->mutex);
}
return FTDM_FAIL;
}
if (ftdmchan->span->state_map) {
ok = ftdm_parse_state_map(ftdmchan, state, ftdmchan->span->state_map);
goto end;
@@ -1353,7 +1357,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direc
ftdm_span_channel_use_count(span, &count);
if (count >= span->chan_count) {
ftdm_log(FTDM_LOG_CRIT, "All circuits are busy.\n");
ftdm_log(FTDM_LOG_CRIT, "All circuits are busy: active=%i max=%i.\n",
count, span->chan_count);
*ftdmchan = NULL;
return FTDM_FAIL;
}
@@ -1623,8 +1628,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_get_sig_status(ftdm_channel_t *ftdmchan,
if (ftdmchan->span->get_channel_sig_status) {
return ftdmchan->span->get_channel_sig_status(ftdmchan, sigstatus);
} else {
ftdm_log(FTDM_LOG_ERROR, "get_channel_sig_status method not implemented!\n");
return FTDM_FAIL;
/* don't log error here, it can be called just to test if its supported */
return FTDM_NOTIMPL;
}
}
+4 -4
View File
@@ -414,7 +414,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
for (i = 0; i < size; i++) {
ints[i] = interrupts[i]->event;
if (interrupts[i]->device != FTDM_INVALID_SOCKET) {
ints[i+numdevices] = interrupts[i]->device;
ints[size+numdevices] = interrupts[i]->device;
numdevices++;
}
}
@@ -446,9 +446,9 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
ints[i].revents = 0;
ints[i].fd = interrupts[i]->readfd;
if (interrupts[i]->device != FTDM_INVALID_SOCKET) {
ints[i+numdevices].events = POLLIN;
ints[i+numdevices].revents = 0;
ints[i+numdevices].fd = interrupts[i]->device;
ints[size+numdevices].events = POLLIN;
ints[size+numdevices].revents = 0;
ints[size+numdevices].fd = interrupts[i]->device;
numdevices++;
}
}
@@ -92,7 +92,6 @@ typedef uint16_t sangoma_boost_request_id_t;
typedef enum {
BST_FREE,
BST_WAITING,
BST_ACK,
BST_READY,
BST_FAIL
} sangoma_boost_request_status_t;
@@ -109,6 +108,13 @@ typedef struct {
int flags;
} sangoma_boost_request_t;
typedef struct {
int call_setup_id;
int last_event_id;
} sangoma_boost_call_t;
#define CALL_DATA(ftdmchan) ((sangoma_boost_call_t*)((ftdmchan)->call_data))
//#define MAX_REQ_ID FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN * FTDM_MAX_CHANNELS_PHYSICAL_SPAN
#define MAX_REQ_ID 6000
@@ -179,7 +185,7 @@ static sangoma_boost_request_id_t __next_request_id(const char *func, int line)
r = ++last_req;
if (r >= MAX_REQ_ID) {
r = i = last_req = 1;
r = last_req = 1;
}
if (req_map[r]) {
@@ -204,6 +210,25 @@ static sangoma_boost_request_id_t __next_request_id(const char *func, int line)
}
#define next_request_id() __next_request_id(__FUNCTION__, __LINE__)
static void print_request_ids(void)
{
sangoma_boost_request_id_t i = 0;
ftdm_mutex_lock(request_mutex);
for (i=1; i<= MAX_REQ_ID; i++){
if (req_map[i]) {
ftdm_log(FTDM_LOG_CRIT, "Used Request ID=%i\n",i);
}
}
ftdm_mutex_unlock(request_mutex);
return;
}
/**
* \brief Finds the channel that triggered an event
* \param span Span where to search the channel
@@ -215,10 +240,26 @@ static ftdm_channel_t *find_ftdmchan(ftdm_span_t *span, sangomabc_short_event_t
{
uint32_t i;
ftdm_channel_t *ftdmchan = NULL;
ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
uint32_t targetspan = BOOST_EVENT_SPAN(sangoma_boost_data->sigmod, event);
uint32_t targetchan = BOOST_EVENT_CHAN(sangoma_boost_data->sigmod, event);
/* NC: Sanity check in case the call setup id does not relate
to span. This can happen if RESTART is received on a
full load. Where stray ACK messages can arrive after
a RESTART has taken place.
*/
if (!span) {
ftdm_log(FTDM_LOG_CRIT, "No Span for Event=%s s%dc%d cid=%d\n",
BOOST_DECODE_EVENT_ID(event->event_id),
event->span,
event->chan,
event->call_setup_id);
return NULL;
}
for(i = 1; i <= span->chan_count; i++) {
if (span->channels[i]->physical_span_id == targetspan && span->channels[i]->physical_chan_id == targetchan) {
ftdmchan = span->channels[i];
@@ -276,12 +317,20 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
* and PRI stack will retransmit a second SETUP after the first timeout, so
* we should allow for at least 8 seconds.
*/
int boost_request_timeout = 10000;
sangoma_boost_request_status_t st;
char dnis[128] = "";
char *gr = NULL;
uint32_t count = 0;
int tg=0;
/* NC: On large number of calls 10 seconds is not enough.
Resetting to 30 seconds. Especially on ss7 when
links are reset during large call volume */
if (!sangoma_boost_data->sigmod) {
boost_request_timeout = 30000;
}
if (sangoma_boost_data->sigmod) {
ftdm_log(FTDM_LOG_CRIT, "This function should not be called when sigmod was configured in boost\n");
@@ -290,12 +339,22 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
}
if (ftdm_test_flag(span, FTDM_SPAN_SUSPENDED)) {
ftdm_log(FTDM_LOG_CRIT, "SPAN is not online.\n");
ftdm_log(FTDM_LOG_CRIT, "SPAN is Suspended.\n");
*ftdmchan = NULL;
return FTDM_FAIL;
}
if (check_congestion(tg)) {
ftdm_log(FTDM_LOG_CRIT, "All circuits are busy. Trunk Group=%i (CONGESTION)\n",tg+1);
*ftdmchan = NULL;
return FTDM_FAIL;
}
if (count >= span->chan_count) {
ftdm_log(FTDM_LOG_CRIT, "All circuits are busy.\n");
*ftdmchan = NULL;
return FTDM_FAIL;
}
ftdm_set_string(dnis, caller_data->dnis.digits);
r = next_request_id();
if (r == 0) {
@@ -303,7 +362,11 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
*ftdmchan = NULL;
return FTDM_FAIL;
}
sangomabc_call_init(&event, caller_data->cid_num.digits, dnis, r);
/* After this point we must release request id before we leave the function
in case of an error. */
ftdm_set_string(dnis, caller_data->dnis.digits);
if ((gr = strchr(dnis, '@'))) {
*gr++ = '\0';
@@ -315,22 +378,14 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
tg--;
}
}
sangomabc_call_init(&event, caller_data->cid_num.digits, dnis, r);
event.trunk_group = tg;
if (check_congestion(tg)) {
ftdm_log(FTDM_LOG_CRIT, "All circuits are busy. Trunk Group=%i (BOOST REQUESTED BACK OFF)\n",tg+1);
*ftdmchan = NULL;
return FTDM_FAIL;
}
ftdm_span_channel_use_count(span, &count);
if (count >= span->chan_count) {
ftdm_log(FTDM_LOG_CRIT, "All circuits are busy.\n");
*ftdmchan = NULL;
return FTDM_FAIL;
}
if (gr && *(gr+1)) {
switch(*gr) {
case 'g':
@@ -373,7 +428,7 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
if (sangomabc_connection_write(&sangoma_boost_data->mcon, &event) <= 0) {
ftdm_log(FTDM_LOG_CRIT, "Failed to tx boost event [%s]\n", strerror(errno));
status = FTDM_FAIL;
status = OUTBOUND_REQUESTS[r].status = FTDM_FAIL;
if (!sangoma_boost_data->sigmod) {
*ftdmchan = NULL;
}
@@ -387,7 +442,7 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
if (!sangoma_boost_data->sigmod) {
*ftdmchan = NULL;
}
ftdm_log(FTDM_LOG_CRIT, "s%dc%d: Csid:%d Timed out waiting for boost channel request response, current status: BST_WAITING\n", (*ftdmchan)->physical_span_id, (*ftdmchan)->physical_chan_id, r);
ftdm_log(FTDM_LOG_CRIT, "Csid:%d Timed out waiting for boost channel request response, current status: BST_WAITING\n", r);
goto done;
}
}
@@ -494,6 +549,7 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(sangoma_boost_outgoing_call)
ftdm_log(FTDM_LOG_DEBUG, "Dialing number %s over boost channel with request id %d\n", event.called_number_digits, r);
if (sangomabc_connection_write(&sangoma_boost_data->mcon, &event) <= 0) {
release_request_id(r);
ftdm_log(FTDM_LOG_CRIT, "Failed to tx boost event [%s]\n", strerror(errno));
return FTDM_FAIL;
}
@@ -550,7 +606,12 @@ static void handle_call_start_ack(sangomabc_connection_t *mcon, sangomabc_short_
uint32_t event_span = BOOST_EVENT_SPAN(mcon->sigmod, event);
uint32_t event_chan = BOOST_EVENT_CHAN(mcon->sigmod, event);
if (nack_map[event->call_setup_id]) {
/* In this scenario outgoing call was alrady stopped
via NACK and now we are expecting an NACK_ACK.
If we receive an ACK its a race condition thus
ignor it */
return;
}
@@ -607,15 +668,43 @@ static void handle_call_start_ack(sangomabc_connection_t *mcon, sangomabc_short_
OUTBOUND_REQUESTS[event->call_setup_id].status = BST_READY;
return;
}
}
} else {
ftdm_assert(!mcon->sigmod, "CALL STOP ACK: Invalid Sigmod Path");
if ((ftdmchan = find_ftdmchan(OUTBOUND_REQUESTS[event->call_setup_id].span, (sangomabc_short_event_t*)event, 1))) {
int r;
/* NC: If we get CALL START ACK and channel is in active state
then we are completely out of sync with the other end.
Treat CALL START ACK as CALL STOP and hangup the current call.
*/
if (ftdmchan->state == FTDM_CHANNEL_STATE_UP ||
ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA ||
ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS) {
ftdm_log(FTDM_LOG_CRIT, "FTDM_CHAN STATE UP/PROG/PROG_MEDIA -> Changed to HANGUP %d:%d\n", event->span+1,event->chan+1);
ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_HANGUP, 0, r);
} else if (ftdm_test_sflag(ftdmchan, SFLAG_HANGUP)) {
/* Do nothing because outgoing STOP will generaate a stop ack */
} else {
ftdm_log(FTDM_LOG_CRIT, "FTDM_CHAN STATE INVALID %s on IN CALL ACK %d:%d\n", ftdm_channel_state2str(ftdmchan->state),event->span+1,event->chan+1);
}
ftdmchan=NULL;
}
}
if (!ftdmchan) {
ftdm_log(FTDM_LOG_CRIT, "START ACK CANT FIND A CHAN %d:%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
} else {
/* only reason to be here is failed to open channel when we we're in sigmod */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
ftdm_set_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG);
}
ftdm_set_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG);
sangomabc_exec_command(mcon,
event->span,
event->chan,
@@ -636,7 +725,7 @@ static void handle_call_done(ftdm_span_t *span, sangomabc_connection_t *mcon, sa
{
ftdm_channel_t *ftdmchan;
int r = 0;
if ((ftdmchan = find_ftdmchan(span, event, 1))) {
ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data;
ftdm_mutex_lock(ftdmchan->mutex);
@@ -677,6 +766,7 @@ static void handle_call_done(ftdm_span_t *span, sangomabc_connection_t *mcon, sa
}
}
/**
* \brief Handler for call start nack event
* \param span Span where event was fired
@@ -718,7 +808,7 @@ static void handle_call_start_nack(ftdm_span_t *span, sangomabc_connection_t *mc
if (event->call_setup_id) {
if (sangoma_boost_data->sigmod) {
ftdmchan = OUTBOUND_REQUESTS[event->call_setup_id].ftdmchan;
ftdmchan->call_data = (void*)(intptr_t)event->event_id;
CALL_DATA(ftdmchan)->last_event_id = event->event_id;
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
} else {
sangomabc_exec_command(mcon,
@@ -740,7 +830,7 @@ static void handle_call_start_nack(ftdm_span_t *span, sangomabc_connection_t *mc
/* if there is no call setup id this should not be an outbound channel for sure */
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND), "Yay, outbound flag should not be set here!\n");
ftdmchan->call_data = (void*)(intptr_t)event->event_id;
CALL_DATA(ftdmchan)->last_event_id = event->event_id;
ftdm_mutex_lock(ftdmchan->mutex);
ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, 0, r);
if (r == FTDM_STATE_CHANGE_SUCCESS) {
@@ -793,7 +883,16 @@ static void handle_call_stop(ftdm_span_t *span, sangomabc_connection_t *mcon, sa
ftdm_mutex_lock(ftdmchan->mutex);
if (ftdm_test_sflag(ftdmchan, SFLAG_HANGUP)) {
if (ftdm_test_sflag(ftdmchan, SFLAG_HANGUP) ||
ftdmchan->state == FTDM_CHANNEL_STATE_DOWN ||
ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
/* NC: Checking for state DOWN because ss7box can
send CALL_STOP twice in a row. If we do not check for
STATE_DOWN we will set the state back to termnating
and block the channel forever
*/
/* racing condition where both sides initiated a hangup
* Do not change current state as channel is already clearing
* itself through local initiated hangup */
@@ -848,8 +947,18 @@ static void handle_call_answer(ftdm_span_t *span, sangomabc_connection_t *mcon,
if ((ftdmchan = find_ftdmchan(span, event, 1))) {
ftdm_mutex_lock(ftdmchan->mutex);
if (ftdmchan->state == FTDM_CHANNEL_STATE_HOLD) {
if (ftdm_test_sflag(ftdmchan, SFLAG_HANGUP) ||
ftdmchan->state == FTDM_CHANNEL_STATE_DOWN ||
ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
/* NC: Do nothing here because we are in process
of stopping the call. So ignore the ANSWER. */
ftdm_log(FTDM_LOG_CRIT, "ANSWER BUT CALL IS HANGUP %d:%d\n", event->span+1,event->chan+1);
} else if (ftdmchan->state == FTDM_CHANNEL_STATE_HOLD) {
ftdmchan->init_state = FTDM_CHANNEL_STATE_UP;
} else {
int r = 0;
ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_UP, 0, r);
@@ -881,6 +990,12 @@ static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, s
if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) {
if ((ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) {
int r;
/* NC: If we get CALL START and channel is in active state
then we are completely out of sync with the other end.
Treat CALL START as CALL STOP and hangup the current call.
*/
if (ftdmchan->state == FTDM_CHANNEL_STATE_UP) {
ftdm_log(FTDM_LOG_CRIT, "ZCHAN STATE UP -> Changed to TERMINATING %d:%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, 0, r);
@@ -1179,8 +1294,12 @@ static int parse_sangoma_event(ftdm_span_t *span, sangomabc_connection_t *mcon,
handle_call_done(span, mcon, event);
break;
case SIGBOOST_EVENT_CALL_START_NACK_ACK:
handle_call_done(span, mcon, event);
nack_map[event->call_setup_id] = 0;
/* On NACK ack span chan are always invalid
All there is to do is to clear the id */
if (event->call_setup_id) {
nack_map[event->call_setup_id] = 0;
release_request_id(event->call_setup_id);
}
break;
case SIGBOOST_EVENT_INSERT_CHECK_LOOP:
handle_call_loop_start(span, mcon, event);
@@ -1246,7 +1365,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
if (!ftdm_test_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG)) {
ftdm_set_sflag_locked(ftdmchan, SFLAG_SENT_FINAL_MSG);
if (ftdmchan->call_data && ((uint32_t)(intptr_t)ftdmchan->call_data == SIGBOOST_EVENT_CALL_START_NACK)) {
if (ftdmchan->call_data && CALL_DATA(ftdmchan)->last_event_id == SIGBOOST_EVENT_CALL_START_NACK) {
sangomabc_exec_command(mcon,
BOOST_SPAN(ftdmchan),
BOOST_CHAN(ftdmchan),
@@ -1266,7 +1385,8 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
}
}
ftdmchan->sflags = 0;
ftdmchan->call_data = NULL;
memset(ftdmchan->call_data,0,sizeof(sangoma_boost_call_t));
if (sangoma_boost_data->sigmod && call_stopped_ack_sent) {
/* we dont want to call ftdm_channel_done just yet until call released is received */
ftdm_log(FTDM_LOG_DEBUG, "Waiting for call release confirmation before declaring chan %d:%d as available \n",
@@ -1457,13 +1577,17 @@ static __inline__ void check_state(ftdm_span_t *span)
uint32_t j;
ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE);
if (susp) {
for (j = 0; j <= span->chan_count; j++) {
ftdm_mutex_lock(span->channels[j]->mutex);
ftdm_clear_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE);
ftdm_channel_set_state(span->channels[j], FTDM_CHANNEL_STATE_RESTART, 0);
state_advance(span->channels[j]);
ftdm_channel_complete_state(span->channels[j]);
ftdm_mutex_unlock(span->channels[j]->mutex);
for(j = 1; j <= span->chan_count; j++) {
if (ftdm_test_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE) || susp) {
ftdm_mutex_lock(span->channels[j]->mutex);
ftdm_clear_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE);
if (susp && span->channels[j]->state != FTDM_CHANNEL_STATE_DOWN) {
ftdm_channel_set_state(span->channels[j], FTDM_CHANNEL_STATE_RESTART, 0);
}
state_advance(span->channels[j]);
ftdm_channel_complete_state(span->channels[j]);
ftdm_mutex_unlock(span->channels[j]->mutex);
}
}
} else {
while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans))) {
@@ -1642,8 +1766,8 @@ static int ftdm_boost_wait_event(ftdm_span_t *span)
sangoma_boost_data->iteration = 0;
}
#endif
res = ftdm_interrupt_multiple_wait(ints, numints, -1);
if (FTDM_SUCCESS != res) {
res = ftdm_interrupt_multiple_wait(ints, numints, 100);
if (FTDM_SUCCESS != res && FTDM_TIMEOUT != res) {
ftdm_log(FTDM_LOG_CRIT, "Unexpected return value from interrupt waiting: %d\n", res);
return -1;
}
@@ -1730,7 +1854,6 @@ static void *ftdm_sangoma_boost_run(ftdm_thread_t *me, void *obj)
if (ftdm_boost_wait_event(span) < 0) {
ftdm_log(FTDM_LOG_ERROR, "ftdm_boost_wait_event failed\n");
goto error;
}
while ((event = ftdm_boost_read_event(span))) {
@@ -1743,7 +1866,6 @@ static void *ftdm_sangoma_boost_run(ftdm_thread_t *me, void *obj)
goto end;
error:
ftdm_log(FTDM_LOG_CRIT, "Boost event processing Error!\n");
end:
@@ -1758,6 +1880,37 @@ end:
return NULL;
}
#if 0
static int sigmod_ss7box_isup_exec_cmd(ftdm_stream_handle_t *stream, char *cmd)
{
FILE *fp;
int status=0;
char path[1024];
fp = popen(cmd, "r");
if (fp == NULL) {
stream->write_function(stream, "%s: -ERR failed to execute cmd: %s\n",
__FILE__,cmd);
return -1;
}
while (fgets(path, sizeof(path)-1, fp) != NULL) {
path[sizeof(path)-1]='\0';
stream->write_function(stream,"%s", path);
}
status = pclose(fp);
if (status == -1) {
/* Error reported by pclose() */
} else {
/* Use macros described under wait() to inspect `status' in order
to determine success/failure of command executed by popen() */
}
return status;
}
#endif
#define FTDM_BOOST_SYNTAX "list sigmods | <sigmod_name> <command>"
/**
@@ -1780,11 +1933,63 @@ static FIO_API_FUNCTION(ftdm_sangoma_boost_api)
if (!strcasecmp(argv[0], "list")) {
if (!strcasecmp(argv[1], "sigmods")) {
if (ftdm_sangoma_boost_list_sigmods(stream) != FTDM_SUCCESS) {
stream->write_function(stream, "%s: -ERR failed to execute cmd\n", __FILE__);
stream->write_function(stream, "-ERR failed to list sigmods\n");
goto done;
}
goto done;
}
if (!strcasecmp(argv[1], "ids")) {
print_request_ids();
goto done;
}
#ifndef __WINDOWS__
#if 0
/* NC: This code crashes the kernel due to fork on heavy fs load */
} else if (!strcasecmp(argv[0], "ss7box_isupd_ckt")) {
if (!strcasecmp(argv[1], "used")) {
stream->write_function(stream, "ss7box_isupd: in use\n", FTDM_BOOST_SYNTAX);
sigmod_ss7box_isup_exec_cmd(stream, (char*) "ckt_report.sh inuse");
} else if (!strcasecmp(argv[1], "reset")) {
stream->write_function(stream, "ss7box_isupd: in reset\n", FTDM_BOOST_SYNTAX);
sigmod_ss7box_isup_exec_cmd(stream, (char*) "ckt_report.sh reset");
} else if (!strcasecmp(argv[1], "ready")) {
stream->write_function(stream, "ss7box_isupd: ready \n", FTDM_BOOST_SYNTAX);
sigmod_ss7box_isup_exec_cmd(stream, (char*) "ckt_report.sh free");
} else {
stream->write_function(stream, "ss7box_isupd: list\n", FTDM_BOOST_SYNTAX);
sigmod_ss7box_isup_exec_cmd(stream, (char*) "ckt_report.sh");
}
goto done;
#endif
#endif
} else if (!strcasecmp(argv[0], "restart")) {
sangomabc_connection_t *pcon;
ftdm_sangoma_boost_data_t *sangoma_boost_data;
ftdm_span_t *span;
int err = ftdm_span_find_by_name(argv[1], &span);
if (FTDM_SUCCESS != err) {
stream->write_function(stream, "-ERR failed to find span by name %s\n",argv[1]);
goto done;
}
sangoma_boost_data = span->signal_data;
pcon = &sangoma_boost_data->pcon;
/* No need to set any span flags because
our RESTART will generate a RESTART from the sig daemon */
sangomabc_exec_commandp(pcon,
0,
0,
-1,
SIGBOOST_EVENT_SYSTEM_RESTART,
0);
goto done;
} else {
boost_sigmod_interface_t *sigmod_iface = NULL;
sigmod_iface = hashtable_search(g_boost_modules_hash, argv[0]);
@@ -1822,7 +2027,7 @@ done:
*/
static FIO_IO_LOAD_FUNCTION(ftdm_sangoma_boost_io_init)
{
assert(fio != NULL);
ftdm_assert(fio != NULL, "fio is NULL");
memset(&ftdm_sangoma_boost_interface, 0, sizeof(ftdm_sangoma_boost_interface));
ftdm_sangoma_boost_interface.name = "boost";
@@ -2205,6 +2410,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_boost_configure_span)
ftdm_dso_lib_t lib = NULL;
char path[255] = "";
char *err = NULL;
int j = 0;
unsigned paramindex = 0;
ftdm_status_t rc = FTDM_SUCCESS;
@@ -2299,6 +2505,14 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_boost_configure_span)
ftdm_set_string(sangoma_boost_data->mcon.cfg.remote_ip, remote_ip);
sangoma_boost_data->mcon.cfg.remote_port = remote_port;
}
for (j = 1; j <= span->chan_count; j++) {
span->channels[j]->call_data = ftdm_calloc(1,sizeof(sangoma_boost_call_t));
if (!span->channels[j]->call_data) {
FAIL_CONFIG_RETURN(FTDM_FAIL);
}
}
span->signal_cb = sig_cb;
span->start = ftdm_sangoma_boost_start;
span->stop = ftdm_sangoma_boost_stop;
@@ -77,7 +77,7 @@ static void sangomabc_print_event_call(sangomabc_connection_t *mcon, sangomabc_e
if (event->event_id == SIGBOOST_EVENT_HEARTBEAT)
return;
ftdm_log(file, func, line, FTDM_LOG_LEVEL_DEBUG, "%s EVENT (%s): %s:(%X) [w%dg%d] CSid=%i Seq=%i Cn=[%s] Cd=[%s] Ci=[%s] Rdnis=[%s]\n",
ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "%s EVENT (%s): %s:(%X) [w%dg%d] CSid=%i Seq=%i Cn=[%s] Cd=[%s] Ci=[%s] Rdnis=[%s]\n",
dir ? "TX":"RX",
priority ? "P":"N",
sangomabc_event_id_name(event->event_id),
@@ -96,7 +96,7 @@ static void sangomabc_print_event_short(sangomabc_connection_t *mcon, sangomabc_
{
if (event->event_id == SIGBOOST_EVENT_HEARTBEAT)
return;
ftdm_log(file, func, line, FTDM_LOG_LEVEL_DEBUG, "%s EVENT (%s): %s:(%X) [s%dc%d] Rc=%i CSid=%i Seq=%i \n",
ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "%s EVENT (%s): %s:(%X) [s%dc%d] Rc=%i CSid=%i Seq=%i \n",
dir ? "TX":"RX",
priority ? "P":"N",
sangomabc_event_id_name(event->event_id),
@@ -51,6 +51,24 @@ enum e_sigboost_event_id_values
SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE = 0x8c, /*140*/
SIGBOOST_EVENT_DIGIT_IN = 0x8d, /*141*/
};
#define BOOST_DECODE_EVENT_ID(id) \
(id==SIGBOOST_EVENT_CALL_START)?"SIGBOOST_EVENT_CALL_START": \
(id==SIGBOOST_EVENT_CALL_START_ACK)?"SIGBOOST_EVENT_CALL_START_ACK": \
(id==SIGBOOST_EVENT_CALL_START_NACK)?"SIGBOOST_EVENT_CALL_START_NACK": \
(id==SIGBOOST_EVENT_CALL_ANSWERED)?"SIGBOOST_EVENT_CALL_ANSWERED": \
(id==SIGBOOST_EVENT_CALL_STOPPED)?"SIGBOOST_EVENT_CALL_STOPPED": \
(id==SIGBOOST_EVENT_CALL_STOPPED_ACK)?"SIGBOOST_EVENT_CALL_STOPPED_ACK": \
(id==SIGBOOST_EVENT_SYSTEM_RESTART)?"SIGBOOST_EVENT_SYSTEM_RESTART": \
(id==SIGBOOST_EVENT_SYSTEM_RESTART_ACK)?"SIGBOOST_EVENT_SYSTEM_RESTART_ACK": \
(id==SIGBOOST_EVENT_CALL_RELEASED)?"SIGBOOST_EVENT_CALL_RELEASED": \
(id==SIGBOOST_EVENT_CALL_PROGRESS)?"SIGBOOST_EVENT_CALL_PROGRESS": \
(id==SIGBOOST_EVENT_HEARTBEAT)?"SIGBOOST_EVENT_HEARTBEAT": \
(id==SIGBOOST_EVENT_INSERT_CHECK_LOOP)?"SIGBOOST_EVENT_INSERT_CHECK_LOOP": \
(id==SIGBOOST_EVENT_REMOVE_CHECK_LOOP)?"SIGBOOST_EVENT_REMOVE_CHECK_LOOP": \
(id==SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE)?"SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE": \
(id==SIGBOOST_EVENT_DIGIT_IN)?"SIGBOOST_EVENT_DIGIT_IN": "Unknown"
enum e_sigboost_release_cause_values
{
SIGBOOST_RELEASE_CAUSE_UNDEFINED = 0,
+3
View File
@@ -827,6 +827,9 @@ FT_DECLARE(char *) ftdm_api_execute(const char *type, const char *cmd);
FT_DECLARE(int) ftdm_vasprintf(char **ret, const char *fmt, va_list ap);
FT_DECLARE(ftdm_status_t) ftdm_channel_set_caller_data(ftdm_channel_t *ftdmchan, ftdm_caller_data_t *caller_data);
FT_DECLARE(void) ftdm_cpu_monitor_disable(void);
FT_DECLARE(ftdm_status_t) ftdm_conf_node_create(const char *name, ftdm_conf_node_t **node, ftdm_conf_node_t *parent);
FT_DECLARE(ftdm_status_t) ftdm_conf_node_add_param(ftdm_conf_node_t *node, const char *param, const char *val);
FT_DECLARE(ftdm_status_t) ftdm_conf_node_destroy(ftdm_conf_node_t *node);
FIO_CODEC_FUNCTION(fio_slin2ulaw);
FIO_CODEC_FUNCTION(fio_ulaw2slin);
+26 -2
View File
@@ -572,6 +572,30 @@ typedef ftdm_status_t (*fio_api_t) FIO_API_ARGS ;
#include "ftdm_dso.h"
#define FTDM_NODE_NAME_SIZE 50
typedef struct ftdm_conf_node_s {
/* node name */
char name[FTDM_NODE_NAME_SIZE];
/* total slots for parameters */
unsigned int t_parameters;
/* current number of parameters */
unsigned int n_parameters;
/* array of parameters */
ftdm_conf_parameter_t *parameters;
/* first node child */
struct ftdm_conf_node_s *child;
/* next node sibling */
struct ftdm_conf_node_s *next;
/* my parent if any */
struct ftdm_conf_node_s *parent;
} ftdm_conf_node_t;
typedef struct {
char name[256];
fio_io_load_t io_load;
@@ -583,9 +607,9 @@ typedef struct {
\brief configure a given span signaling
\see sig_configure
This is just like sig_configure but receives
an array of paramters instead of va_list
an an ftdm_conf_node_t instead
I'd like to deprecate sig_configure and move
all modules to use sigparam_configure
all modules to use configure_span_signaling
*/
fio_configure_span_signaling_t configure_span_signaling;
ftdm_dso_lib_t lib;