Merged latest FreeTDM code from Sangoma's repo

Merge remote branch 'smgfs/master'

Conflicts:
	build/modules.conf.in
	configure.in
	libs/esl/fs_cli.c
	libs/freetdm/mod_freetdm/mod_freetdm.c
	libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
	libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c
	libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c
	libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c
	src/include/switch_types.h
	src/mod/applications/mod_commands/mod_commands.c
	src/mod/applications/mod_spandsp/mod_spandsp.c
	src/mod/endpoints/mod_opal/mod_opal.cpp
	src/mod/endpoints/mod_opal/mod_opal.h
	src/mod/endpoints/mod_sofia/mod_sofia.h
	src/mod/endpoints/mod_sofia/rtp.c
	src/switch.c
	src/switch_core.c
	src/switch_rtp.c
This commit is contained in:
David Yat Sin 2012-09-12 11:05:39 -04:00
commit 4340c4d74c
31 changed files with 9223 additions and 911 deletions

View File

@ -214,6 +214,8 @@ ftmod_sangoma_ss7_la_SOURCES = \
$(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c \
$(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c \
$(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c \
$(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_m2ua_xml.c \
$(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_m2ua.c \
$(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c
ftmod_sangoma_ss7_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) -D_GNU_SOURCE

View File

@ -13,7 +13,7 @@ cpu_monitoring_interval => 1000
cpu_set_alarm_threshold => 80
; At what CPU percentage stop the CPU alarm
cpu_reset_alarm_threshold => 70
cpu_clear_alarm_threshold => 70
; Which action to take when the CPU alarm is raised
; it can be warn and/or reject calls

View File

@ -0,0 +1,43 @@
SS7 Native Bridge
Native bridge is enabled on 2 conditions:
* The SIP header FreeTDM-TransUUID is set in the originating leg and matches a freetdm channel
* The variable freetdm_native_sigbridge is true and the originating leg is also a freetdm channel
Some coding rules apply to this feature:
- Each channel is responsible for clearning its own peer_data and event queue
at the end of the call (when moving to DOWN state)
- Each channel dequeues messages only from its own queue and enqueues messages
in the peer's queue, with the only exception being messages received before
the bridge is stablished (IAM for sure and possible SAM messages) because
if the bridge is not yet stablished the messages must be queued by the channel
in its own queue temporarily until the bridge is ready
- When the bridge is ready it is the responsibility of the incoming channel to
move the messages that stored temporarily in its own queue to the bridged peer queue
- During hangup, each channel is responsible for moving itself to DOWN. The procedure
however differs slightly depending on the hangup conditions
If the user requests hangup (ie, FreeSWITCH) the request will be noted by setting the
FTDM_CHANNEL_USER_HANGUP flag but will not be processed yet because call control is
driven only by the link messages (so no hangup from ESL or command line allowed)
When REL message comes, the channel receiving it must move to TERMINATING state and:
- If the user has not hangup yet (FTDM_CHANNEL_USER_HANGUP flag not set) then
notify the user via SIGEVENT_STOP and wait for the user to move to HANGUP
state by calling ftdm_channel_call_hangup() before sending RLC
- If the user did hangup already (FTDM_CHANNEL_USER_HANGUP flag is set) then
skip user notification and move to HANGUP state directly where the RLC message
will be sent
- On HANGUP state the RLC is sent and the channel is moved to DOWN, final state
The peer channel will forward the REL message and wait for RLC from the network, when
RLC is received the channel can move straight to DOWN itself because the peer channel
is completing its own shutdown procedure when it received the REL message

View File

@ -4,6 +4,7 @@ BASE=../../..
FT_DIR=..
VERBOSE=1
FTLA=$(FT_DIR)/libfreetdm.la
LOCAL_OBJS=tdm.o
LOCAL_CFLAGS=-I$(FT_DIR)/src/include -I$(FT_DIR)/src/isdn/include $(FT_CFLAGS)
LOCAL_LDFLAGS=-L$(FT_DIR) -lfreetdm
include $(BASE)/build/modmake.rules

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,712 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Mathieu Rene <mrene@avgs.ca>
*
* tdm.c -- FreeTDM Controllable Channel Module
*
*/
#include <switch.h>
#include "freetdm.h"
void ctdm_init(switch_loadable_module_interface_t *module_interface);
/* Parameters */
#define kSPAN_ID "span"
#define kCHAN_ID "chan"
#define kSPAN_NAME "span_name"
#define kPREBUFFER_LEN "prebuffer_len"
#define kECHOCANCEL "echo_cancel"
static struct {
switch_memory_pool_t *pool;
switch_endpoint_interface_t *endpoint_interface;
} ctdm;
typedef struct {
int span_id;
int chan_id;
ftdm_channel_t *ftdm_channel;
switch_core_session_t *session;
switch_codec_t read_codec, write_codec;
switch_frame_t read_frame;
int prebuffer_len;
unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
} ctdm_private_t;
static switch_status_t channel_on_init(switch_core_session_t *session);
static switch_status_t channel_on_destroy(switch_core_session_t *session);
static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
switch_caller_profile_t *outbound_profile,
switch_core_session_t **new_session,
switch_memory_pool_t **pool,
switch_originate_flag_t flags, switch_call_cause_t *cancel_cause);
static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg);
static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event);
static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf);
static ftdm_status_t ctdm_span_prepare(ftdm_span_t *span);
switch_state_handler_table_t ctdm_state_handlers = {
.on_init = channel_on_init,
.on_destroy = channel_on_destroy
};
switch_io_routines_t ctdm_io_routines = {
.send_dtmf = channel_send_dtmf,
.outgoing_channel = channel_outgoing_channel,
.read_frame = channel_read_frame,
.write_frame = channel_write_frame,
.receive_message = channel_receive_message,
.receive_event = channel_receive_event
};
static void ctdm_report_alarms(ftdm_channel_t *channel)
{
switch_event_t *event = NULL;
ftdm_alarm_flag_t alarmflag = 0;
if (switch_event_create(&event, SWITCH_EVENT_TRAP) != SWITCH_STATUS_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "failed to create alarms events\n");
return;
}
if (ftdm_channel_get_alarms(channel, &alarmflag) != FTDM_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve alarms %s:%d\n", ftdm_channel_get_span_name(channel), ftdm_channel_get_id(channel));
return;
}
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-name", "%s", ftdm_channel_get_span_name(channel));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-number", "%d", ftdm_channel_get_span_id(channel));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "chan-number", "%d", ftdm_channel_get_id(channel));
if (alarmflag) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-trap");
} else {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-clear");
}
if (alarmflag & FTDM_ALARM_RED) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "red");
}
if (alarmflag & FTDM_ALARM_YELLOW) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "yellow");
}
if (alarmflag & FTDM_ALARM_RAI) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "rai");
}
if (alarmflag & FTDM_ALARM_BLUE) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "blue");
}
if (alarmflag & FTDM_ALARM_AIS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "ais");
}
if (alarmflag & FTDM_ALARM_GENERAL) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "general");
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Reporting [%s] alarms for %s:%d\n",
(alarmflag?"ftdm-alarm-trap":"ftdm-alarm-clear"), ftdm_channel_get_span_name(channel), ftdm_channel_get_id(channel));
switch_event_fire(&event);
return;
}
static ftdm_channel_t *ctdm_get_channel_from_event(switch_event_t *event, ftdm_span_t *span)
{
uint32_t chan_id = 0;
const char *chan_number = NULL;
chan_number = switch_event_get_header(event, "chan-number");
if (zstr(chan_number)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No channel number specified\n");
return NULL;
}
chan_id = atoi(chan_number);
if (!chan_id) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid channel number:%s\n", chan_number);
return NULL;
}
return ftdm_span_get_channel_ph(span, chan_id);
}
static void ctdm_event_handler(switch_event_t *event)
{
ftdm_status_t status = FTDM_FAIL;
switch(event->event_id) {
case SWITCH_EVENT_TRAP:
{
ftdm_span_t *span = NULL;
ftdm_channel_t *channel = NULL;
const char *span_name = NULL;
const char *cond = switch_event_get_header(event, "condition");
const char *command = switch_event_get_header(event, "command");
if (zstr(cond)) {
return;
}
span_name = switch_event_get_header(event, "span-name");
if (ftdm_span_find_by_name(span_name, &span) != FTDM_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find span [%s]\n", span_name);
return;
}
if (!strcmp(cond, "mg-tdm-prepare")) {
status = ctdm_span_prepare(span);
if (status == FTDM_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s:prepared successfully\n", span_name);
} else if (status != FTDM_EINVAL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s:Failed to prepare span\n", span_name);
}
} else if (!strcmp(cond, "mg-tdm-check")) {
channel = ctdm_get_channel_from_event(event, span);
if (!channel) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find channel\n");
return;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Requesting alarm status for %s:%d\n",
ftdm_channel_get_span_name(channel), ftdm_channel_get_id(channel));
ctdm_report_alarms(channel);
} else if (!strcmp(cond, "mg-tdm-dtmfremoval")) {
uint8_t enable = 0;
channel = ctdm_get_channel_from_event(event, span);
if (!channel) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find channel\n");
return;
}
if (zstr(command)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s:No command specified for mg-tdm-dtmfremoval\n", span_name);
return;
}
if (!strcmp(command, "enable")) {
enable = 1;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s DTMF-removal for %s:%d\n",
enable ? "Enabling" : "Disabling", ftdm_channel_get_span_name(channel), ftdm_channel_get_id(channel));
ftdm_channel_command(channel, enable ? FTDM_COMMAND_ENABLE_DTMF_REMOVAL : FTDM_COMMAND_DISABLE_DTMF_REMOVAL, 0);
}
}
break;
default:
break;
}
return;
}
void ctdm_init(switch_loadable_module_interface_t *module_interface)
{
switch_endpoint_interface_t *endpoint_interface;
ctdm.pool = module_interface->pool;
endpoint_interface = switch_loadable_module_create_interface(module_interface, SWITCH_ENDPOINT_INTERFACE);
endpoint_interface->interface_name = "tdm";
endpoint_interface->io_routines = &ctdm_io_routines;
endpoint_interface->state_handler = &ctdm_state_handlers;
ctdm.endpoint_interface = endpoint_interface;
switch_event_bind("mod_freetdm", SWITCH_EVENT_TRAP, SWITCH_EVENT_SUBCLASS_ANY, ctdm_event_handler, NULL);
}
static FIO_SIGNAL_CB_FUNCTION(on_signal_cb)
{
uint32_t chanid, spanid;
switch_event_t *event = NULL;
ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE;
chanid = ftdm_channel_get_id(sigmsg->channel);
spanid = ftdm_channel_get_span_id(sigmsg->channel);
switch(sigmsg->event_id) {
case FTDM_SIGEVENT_ALARM_CLEAR:
case FTDM_SIGEVENT_ALARM_TRAP:
{
if (ftdm_channel_get_alarms(sigmsg->channel, &alarmbits) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "failed to retrieve alarms\n");
return FTDM_FAIL;
}
if (switch_event_create(&event, SWITCH_EVENT_TRAP) != SWITCH_STATUS_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "failed to create alarms events\n");
return FTDM_FAIL;
}
if (sigmsg->event_id == FTDM_SIGEVENT_ALARM_CLEAR) {
ftdm_log(FTDM_LOG_NOTICE, "Alarm cleared on channel %d:%d\n", spanid, chanid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-clear");
} else {
ftdm_log(FTDM_LOG_NOTICE, "Alarm raised on channel %d:%d\n", spanid, chanid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-trap");
}
}
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unhandled event %d\n", sigmsg->event_id);
break;
}
if (event) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-name", "%s", ftdm_channel_get_span_name(sigmsg->channel));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-number", "%d", ftdm_channel_get_span_id(sigmsg->channel));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "chan-number", "%d", ftdm_channel_get_id(sigmsg->channel));
if (alarmbits & FTDM_ALARM_RED) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "red");
}
if (alarmbits & FTDM_ALARM_YELLOW) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "yellow");
}
if (alarmbits & FTDM_ALARM_RAI) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "rai");
}
if (alarmbits & FTDM_ALARM_BLUE) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "blue");
}
if (alarmbits & FTDM_ALARM_AIS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "ais");
}
if (alarmbits & FTDM_ALARM_GENERAL) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "general");
}
switch_event_fire(&event);
}
return FTDM_SUCCESS;
}
static ftdm_status_t ctdm_span_prepare(ftdm_span_t *span)
{
if (ftdm_span_register_signal_cb(span, on_signal_cb) != FTDM_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register signal CB\n");
return FTDM_FAIL;
}
return ftdm_span_start(span);
}
static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
switch_caller_profile_t *outbound_profile,
switch_core_session_t **new_session,
switch_memory_pool_t **pool,
switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
{
const char *szchanid = switch_event_get_header(var_event, kCHAN_ID),
*span_name = switch_event_get_header(var_event, kSPAN_NAME),
*szprebuffer_len = switch_event_get_header(var_event, kPREBUFFER_LEN);
int chan_id;
int span_id;
switch_caller_profile_t *caller_profile;
ftdm_span_t *span;
ftdm_channel_t *chan;
switch_channel_t *channel;
char name[128];
const char *dname;
ftdm_codec_t codec;
uint32_t interval;
ctdm_private_t *tech_pvt = NULL;
if (zstr(szchanid) || zstr(span_name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Both ["kSPAN_ID"] and ["kCHAN_ID"] have to be set.\n");
goto fail;
}
chan_id = atoi(szchanid);
if (ftdm_span_find_by_name(span_name, &span) == FTDM_SUCCESS) {
span_id = ftdm_span_get_id(span);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find span [%s]\n", span_name);
goto fail;
}
if (!(*new_session = switch_core_session_request(ctdm.endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, 0, pool))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't request session.\n");
goto fail;
}
channel = switch_core_session_get_channel(*new_session);
if (ftdm_channel_open_ph(span_id, chan_id, &chan) != FTDM_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't open span or channel.\n");
goto fail;
}
span = ftdm_channel_get_span(chan);
tech_pvt = switch_core_session_alloc(*new_session, sizeof *tech_pvt);
tech_pvt->chan_id = chan_id;
tech_pvt->span_id = span_id;
tech_pvt->ftdm_channel = chan;
tech_pvt->session = *new_session;
tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
tech_pvt->read_frame.data = tech_pvt->databuf;
tech_pvt->prebuffer_len = zstr(szprebuffer_len) ? 0 : atoi(szprebuffer_len);
switch_core_session_set_private(*new_session, tech_pvt);
caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
switch_channel_set_caller_profile(channel, caller_profile);
snprintf(name, sizeof(name), "tdm/%d:%d", span_id, chan_id);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connect outbound channel %s\n", name);
switch_channel_set_name(channel, name);
switch_channel_set_state(channel, CS_INIT);
if (FTDM_SUCCESS != ftdm_channel_command(chan, FTDM_COMMAND_GET_CODEC, &codec)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve channel codec.\n");
return SWITCH_STATUS_GENERR;
}
if (FTDM_SUCCESS != ftdm_channel_command(chan, FTDM_COMMAND_GET_INTERVAL, &interval)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve channel interval.\n");
return SWITCH_STATUS_GENERR;
}
if (FTDM_SUCCESS != ftdm_channel_command(chan, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tech_pvt->prebuffer_len)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set channel pre buffer size.\n");
return SWITCH_STATUS_GENERR;
}
if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to set enable echo cancellation.\n");
}
switch(codec) {
case FTDM_CODEC_ULAW:
{
dname = "PCMU";
}
break;
case FTDM_CODEC_ALAW:
{
dname = "PCMA";
}
break;
case FTDM_CODEC_SLIN:
{
dname = "L16";
}
break;
default:
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid codec value retrieved from channel, codec value: %d\n", codec);
goto fail;
}
}
if (switch_core_codec_init(&tech_pvt->read_codec,
dname,
NULL,
8000,
interval,
1,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
goto fail;
} else {
if (switch_core_codec_init(&tech_pvt->write_codec,
dname,
NULL,
8000,
interval,
1,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
switch_core_codec_destroy(&tech_pvt->read_codec);
goto fail;
}
}
if (switch_core_session_set_read_codec(*new_session, &tech_pvt->read_codec) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set read codec?\n");
goto fail;
}
if (switch_core_session_set_write_codec(*new_session, &tech_pvt->write_codec) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set write codec?\n");
}
if (switch_core_session_thread_launch(*new_session) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't start session thread.\n");
goto fail;
}
switch_channel_mark_answered(channel);
return SWITCH_CAUSE_SUCCESS;
fail:
if (tech_pvt) {
if (tech_pvt->ftdm_channel) {
ftdm_channel_close(&tech_pvt->ftdm_channel);
}
if (tech_pvt->read_codec.implementation) {
switch_core_codec_destroy(&tech_pvt->read_codec);
}
if (tech_pvt->write_codec.implementation) {
switch_core_codec_destroy(&tech_pvt->write_codec);
}
}
if (*new_session) {
switch_core_session_destroy(new_session);
}
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
}
static switch_status_t channel_on_init(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_channel_set_state(channel, CS_CONSUME_MEDIA);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t channel_on_destroy(switch_core_session_t *session)
{
ctdm_private_t *tech_pvt = switch_core_session_get_private(session);
if ((tech_pvt = switch_core_session_get_private(session))) {
if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to enable echo cancellation.\n");
}
if (tech_pvt->read_codec.implementation) {
switch_core_codec_destroy(&tech_pvt->read_codec);
}
if (tech_pvt->write_codec.implementation) {
switch_core_codec_destroy(&tech_pvt->write_codec);
}
ftdm_channel_close(&tech_pvt->ftdm_channel);
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
{
ftdm_wait_flag_t wflags = FTDM_READ;
ftdm_status_t status;
ctdm_private_t *tech_pvt;
const char *name;
switch_channel_t *channel;
int chunk;
uint32_t span_id, chan_id;
ftdm_size_t len;
char dtmf[128] = "";
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL);
name = switch_channel_get_name(channel);
top:
wflags = FTDM_READ;
chunk = ftdm_channel_get_io_interval(tech_pvt->ftdm_channel) * 2;
status = ftdm_channel_wait(tech_pvt->ftdm_channel, &wflags, chunk);
span_id = ftdm_channel_get_span_id(tech_pvt->ftdm_channel);
chan_id = ftdm_channel_get_id(tech_pvt->ftdm_channel);
if (status == FTDM_FAIL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id);
goto fail;
}
if (status == FTDM_TIMEOUT) {
goto top;
}
if (!(wflags & FTDM_READ)) {
goto top;
}
len = tech_pvt->read_frame.buflen;
if (ftdm_channel_read(tech_pvt->ftdm_channel, tech_pvt->read_frame.data, &len) != FTDM_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id);
}
*frame = &tech_pvt->read_frame;
tech_pvt->read_frame.datalen = (uint32_t)len;
tech_pvt->read_frame.samples = tech_pvt->read_frame.datalen;
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
if (ftdm_channel_get_codec(tech_pvt->ftdm_channel) == FTDM_CODEC_SLIN) {
tech_pvt->read_frame.samples /= 2;
}
while (ftdm_channel_dequeue_dtmf(tech_pvt->ftdm_channel, dtmf, sizeof(dtmf))) {
switch_dtmf_t _dtmf = { 0, switch_core_default_dtmf_duration(0) };
char *p;
for (p = dtmf; p && *p; p++) {
if (is_dtmf(*p)) {
_dtmf.digit = *p;
ftdm_log(FTDM_LOG_DEBUG, "Queuing DTMF [%c] in channel %s device %d:%d\n", *p, name, span_id, chan_id);
switch_channel_queue_dtmf(channel, &_dtmf);
}
}
}
return SWITCH_STATUS_SUCCESS;
fail:
return SWITCH_STATUS_GENERR;
}
static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
{
ftdm_wait_flag_t wflags = FTDM_WRITE;
ctdm_private_t *tech_pvt;
const char *name;
switch_channel_t *channel;
uint32_t span_id, chan_id;
ftdm_size_t len;
unsigned char data[SWITCH_RECOMMENDED_BUFFER_SIZE] = {0};
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL);
span_id = ftdm_channel_get_span_id(tech_pvt->ftdm_channel);
chan_id = ftdm_channel_get_id(tech_pvt->ftdm_channel);
name = switch_channel_get_name(channel);
if (switch_test_flag(frame, SFF_CNG)) {
frame->data = data;
frame->buflen = sizeof(data);
if ((frame->datalen = tech_pvt->write_codec.implementation->encoded_bytes_per_packet) > frame->buflen) {
goto fail;
}
memset(data, 255, frame->datalen);
}
wflags = FTDM_WRITE;
ftdm_channel_wait(tech_pvt->ftdm_channel, &wflags, ftdm_channel_get_io_interval(tech_pvt->ftdm_channel) * 10);
if (!(wflags & FTDM_WRITE)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Dropping frame! (write not ready) in channel %s device %d:%d!\n", name, span_id, chan_id);
return SWITCH_STATUS_SUCCESS;
}
len = frame->datalen;
if (ftdm_channel_write(tech_pvt->ftdm_channel, frame->data, frame->buflen, &len) != FTDM_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Failed to write to channel %s device %d:%d!\n", name, span_id, chan_id);
}
return SWITCH_STATUS_SUCCESS;
fail:
return SWITCH_STATUS_GENERR;
}
static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
{
ctdm_private_t *tech_pvt = NULL;
char tmp[2] = "";
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL);
tmp[0] = dtmf->digit;
ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_SEND_DTMF, tmp);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
{
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event)
{
const char *command = switch_event_get_header(event, "command");
ctdm_private_t *tech_pvt = switch_core_session_get_private(session);
if (!zstr(command)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeTDM received %s command \n",command);
if (!strcasecmp(command, kPREBUFFER_LEN)) {
const char *szval = switch_event_get_header(event, kPREBUFFER_LEN);
int val = !zstr(szval) ? atoi(szval) : 0;
if (tech_pvt->prebuffer_len == val) {
tech_pvt->prebuffer_len = val;
if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tech_pvt->prebuffer_len)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set channel pre buffer size.\n");
return SWITCH_STATUS_GENERR;
}
}
} else if (!strcasecmp(command, kECHOCANCEL)) {
const char *szval = switch_event_get_header(event, kECHOCANCEL);
int enabled = !!switch_true(szval);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeTDM sending echo cancel [%s] command \n",enabled ? "enable" : "disable");
if (FTDM_SUCCESS != ftdm_channel_command(tech_pvt->ftdm_channel, enabled ? FTDM_COMMAND_ENABLE_ECHOCANCEL : FTDM_COMMAND_DISABLE_ECHOCANCEL, NULL)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to %s echo cancellation.\n", enabled ? "enable" : "disable");
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeTDM received unknown command [%s] \n",command);
}
}
return SWITCH_STATUS_SUCCESS;
}

View File

@ -36,10 +36,10 @@
* David Yat Sin <dyatsin@sangoma.com>
*
*/
#define _GNU_SOURCE
#include "private/ftdm_core.h"
#include <stdarg.h>
#include <ctype.h>
#ifdef WIN32
#include <io.h>
#endif
@ -52,9 +52,7 @@
struct tm *localtime_r(const time_t *clock, struct tm *result);
#endif
#define FORCE_HANGUP_TIMER 3000
#define SPAN_PENDING_CHANS_QUEUE_SIZE 1000
#define SPAN_PENDING_SIGNALS_QUEUE_SIZE 1000
#define FORCE_HANGUP_TIMER 30000
#define FTDM_READ_TRACE_INDEX 0
#define FTDM_WRITE_TRACE_INDEX 1
#define MAX_CALLIDS 6000
@ -64,11 +62,78 @@ struct tm *localtime_r(const time_t *clock, struct tm *result);
ftdm_time_t time_last_throttle_log = 0;
ftdm_time_t time_current_throttle_log = 0;
typedef struct val_str {
const char *str;
unsigned long long val;
} val_str_t;
static val_str_t channel_flag_strs[] = {
{ "configured" , FTDM_CHANNEL_CONFIGURED},
{ "ready", FTDM_CHANNEL_READY},
{ "open", FTDM_CHANNEL_OPEN},
{ "dtmf-detect", FTDM_CHANNEL_DTMF_DETECT},
{ "suppress-dtmf", FTDM_CHANNEL_SUPRESS_DTMF},
{ "transcode", FTDM_CHANNEL_TRANSCODE},
{ "buffer", FTDM_CHANNEL_BUFFER},
{ "in-thread", FTDM_CHANNEL_INTHREAD},
{ "wink", FTDM_CHANNEL_WINK},
{ "flash", FTDM_CHANNEL_FLASH},
{ "state-change", FTDM_CHANNEL_STATE_CHANGE},
{ "hold", FTDM_CHANNEL_HOLD},
{ "in-use", FTDM_CHANNEL_INUSE},
{ "off-hook", FTDM_CHANNEL_OFFHOOK},
{ "ringing", FTDM_CHANNEL_RINGING},
{ "progress-detect", FTDM_CHANNEL_PROGRESS_DETECT},
{ "callerid-detect", FTDM_CHANNEL_CALLERID_DETECT},
{ "outbound", FTDM_CHANNEL_OUTBOUND},
{ "suspended", FTDM_CHANNEL_SUSPENDED},
{ "3-way", FTDM_CHANNEL_3WAY},
{ "progress", FTDM_CHANNEL_PROGRESS},
{ "media", FTDM_CHANNEL_MEDIA},
{ "answered", FTDM_CHANNEL_ANSWERED},
{ "mute", FTDM_CHANNEL_MUTE},
{ "use-rx-gain", FTDM_CHANNEL_USE_RX_GAIN},
{ "use-tx-gain", FTDM_CHANNEL_USE_TX_GAIN},
{ "in-alarm", FTDM_CHANNEL_IN_ALARM},
{ "sig-up", FTDM_CHANNEL_SIG_UP},
{ "user-hangup", FTDM_CHANNEL_USER_HANGUP},
{ "rx-disabled", FTDM_CHANNEL_RX_DISABLED},
{ "tx-disabled", FTDM_CHANNEL_TX_DISABLED},
{ "call-started", FTDM_CHANNEL_CALL_STARTED},
{ "non-block", FTDM_CHANNEL_NONBLOCK},
{ "ind-ack-pending", FTDM_CHANNEL_IND_ACK_PENDING},
{ "blocking", FTDM_CHANNEL_BLOCKING},
{ "media", FTDM_CHANNEL_DIGITAL_MEDIA},
{ "native-sigbridge", FTDM_CHANNEL_NATIVE_SIGBRIDGE},
{ "invalid", FTDM_CHANNEL_MAX_FLAG},
};
static val_str_t span_flag_strs[] = {
{ "configured", FTDM_SPAN_CONFIGURED},
{ "started", FTDM_SPAN_STARTED},
{ "state-change", FTDM_SPAN_STATE_CHANGE},
{ "suspended", FTDM_SPAN_SUSPENDED},
{ "in-thread", FTDM_SPAN_IN_THREAD},
{ "stop-thread", FTDM_SPAN_STOP_THREAD},
{ "use-chan-queue", FTDM_SPAN_USE_CHAN_QUEUE},
{ "suggest-chan-id", FTDM_SPAN_SUGGEST_CHAN_ID},
{ "use-av-rate", FTDM_SPAN_USE_AV_RATE},
{ "power-saving", FTDM_SPAN_PWR_SAVING},
{ "signals-queue", FTDM_SPAN_USE_SIGNALS_QUEUE},
{ "proceed-state", FTDM_SPAN_USE_PROCEED_STATE},
{ "skip-state", FTDM_SPAN_USE_SKIP_STATES},
{ "non-stoppable", FTDM_SPAN_NON_STOPPABLE},
{ "use-transfer", FTDM_SPAN_USE_TRANSFER},
};
static ftdm_status_t ftdm_call_set_call_id(ftdm_channel_t *fchan, ftdm_caller_data_t *caller_data);
static ftdm_status_t ftdm_call_clear_call_id(ftdm_caller_data_t *caller_data);
static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan);
static ftdm_status_t ftdm_channel_sig_indicate(ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication, ftdm_usrmsg_t *usrmsg);
static const char *ftdm_val2str(unsigned long long val, val_str_t *val_str_table, ftdm_size_t array_size, const char *default_str);
static unsigned long long ftdm_str2val(const char *str, val_str_t *val_str_table, ftdm_size_t array_size, unsigned long long default_val);
static int time_is_init = 0;
@ -171,7 +236,7 @@ static void stop_chan_io_dump(ftdm_io_dump_t *dump)
return;
}
ftdm_safe_free(dump->buffer);
memset(dump, 0, sizeof(dump));
memset(dump, 0, sizeof(*dump));
}
static ftdm_status_t start_chan_io_dump(ftdm_channel_t *chan, ftdm_io_dump_t *dump, ftdm_size_t size)
@ -223,7 +288,7 @@ typedef struct {
uint32_t interval;
uint8_t alarm_action_flags;
uint8_t set_alarm_threshold;
uint8_t reset_alarm_threshold;
uint8_t clear_alarm_threshold;
ftdm_interrupt_t *interrupt;
} cpu_monitor_t;
@ -1060,7 +1125,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_add_channel(ftdm_span_t *span, ftdm_socket_t
i++;
}
ftdm_set_flag(new_chan, FTDM_CHANNEL_CONFIGURED | FTDM_CHANNEL_READY);
ftdm_set_flag(new_chan, FTDM_CHANNEL_CONFIGURED | FTDM_CHANNEL_READY);
new_chan->state = FTDM_CHANNEL_STATE_DOWN;
new_chan->state_status = FTDM_STATE_STATUS_COMPLETED;
*chan = new_chan;
@ -1413,13 +1478,24 @@ FT_DECLARE(ftdm_status_t) ftdm_group_channel_use_count(ftdm_group_t *group, uint
static __inline__ int chan_is_avail(ftdm_channel_t *check)
{
if (!ftdm_test_flag(check, FTDM_CHANNEL_READY) ||
!ftdm_test_flag(check, FTDM_CHANNEL_SIG_UP) ||
ftdm_test_flag(check, FTDM_CHANNEL_INUSE) ||
ftdm_test_flag(check, FTDM_CHANNEL_SUSPENDED) ||
ftdm_test_flag(check, FTDM_CHANNEL_IN_ALARM) ||
check->state != FTDM_CHANNEL_STATE_DOWN) {
return 0;
if ((check->span->signal_type == FTDM_SIGTYPE_M2UA) ||
(check->span->signal_type == FTDM_SIGTYPE_NONE)) {
if (!ftdm_test_flag(check, FTDM_CHANNEL_READY) ||
ftdm_test_flag(check, FTDM_CHANNEL_INUSE) ||
ftdm_test_flag(check, FTDM_CHANNEL_SUSPENDED) ||
ftdm_test_flag(check, FTDM_CHANNEL_IN_ALARM) ||
check->state != FTDM_CHANNEL_STATE_DOWN) {
return 0;
}
} else {
if (!ftdm_test_flag(check, FTDM_CHANNEL_READY) ||
!ftdm_test_flag(check, FTDM_CHANNEL_SIG_UP) ||
ftdm_test_flag(check, FTDM_CHANNEL_INUSE) ||
ftdm_test_flag(check, FTDM_CHANNEL_SUSPENDED) ||
ftdm_test_flag(check, FTDM_CHANNEL_IN_ALARM) ||
check->state != FTDM_CHANNEL_STATE_DOWN) {
return 0;
}
}
return 1;
}
@ -1825,7 +1901,7 @@ done:
return status;
}
static ftdm_status_t _ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan)
static ftdm_status_t _ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan, uint8_t physical)
{
ftdm_channel_t *check = NULL;
ftdm_span_t *span = NULL;
@ -1854,14 +1930,46 @@ static ftdm_status_t _ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm
goto done;
}
if (chan_id < 1 || chan_id > span->chan_count) {
ftdm_log(FTDM_LOG_ERROR, "Invalid channel %d to open in span %d\n", chan_id, span_id);
goto done;
}
if (physical) { /* Open by physical */
ftdm_channel_t *fchan = NULL;
ftdm_iterator_t *citer = NULL;
ftdm_iterator_t *curr = NULL;
if (!(check = span->channels[chan_id])) {
ftdm_log(FTDM_LOG_CRIT, "Wow, no channel %d in span %d\n", chan_id, span_id);
goto done;
if (chan_id < 1) {
ftdm_log(FTDM_LOG_ERROR, "Invalid physical channel %d to open in span %d\n", chan_id, span_id);
status = FTDM_FAIL;
goto done;
}
citer = ftdm_span_get_chan_iterator(span, NULL);
if (!citer) {
status = ENOMEM;
goto done;
}
for (curr = citer ; curr; curr = ftdm_iterator_next(curr)) {
fchan = ftdm_iterator_current(curr);
if (fchan->physical_chan_id == chan_id) {
check = fchan;
break;
}
}
ftdm_iterator_free(citer);
if (!check) {
ftdm_log(FTDM_LOG_CRIT, "Wow, no physical channel %d in span %d\n", chan_id, span_id);
goto done;
}
} else { /* Open by logical */
if (chan_id < 1 || chan_id > span->chan_count) {
ftdm_log(FTDM_LOG_ERROR, "Invalid channel %d to open in span %d\n", chan_id, span_id);
goto done;
}
if (!(check = span->channels[chan_id])) {
ftdm_log(FTDM_LOG_CRIT, "Wow, no channel %d in span %d\n", chan_id, span_id);
goto done;
}
}
ftdm_channel_lock(check);
@ -1932,7 +2040,18 @@ done:
FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan)
{
ftdm_status_t status;
status = _ftdm_channel_open(span_id, chan_id, ftdmchan);
status = _ftdm_channel_open(span_id, chan_id, ftdmchan, 0);
if (status == FTDM_SUCCESS) {
ftdm_channel_t *fchan = *ftdmchan;
ftdm_channel_unlock(fchan);
}
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_channel_open_ph(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan)
{
ftdm_status_t status;
status = _ftdm_channel_open(span_id, chan_id, ftdmchan, 1);
if (status == FTDM_SUCCESS) {
ftdm_channel_t *fchan = *ftdmchan;
ftdm_channel_unlock(fchan);
@ -2229,6 +2348,15 @@ static ftdm_status_t _ftdm_channel_call_hangup_nl(const char *file, const char *
{
ftdm_status_t status = FTDM_SUCCESS;
/* In native sigbridge mode we ignore hangup requests from the user and hangup only when the signaling module decides it */
if (ftdm_test_flag(chan, FTDM_CHANNEL_NATIVE_SIGBRIDGE) && chan->state != FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan_ex(chan, file, func, line, FTDM_LOG_LEVEL_DEBUG,
"Ignoring hangup in channel in state %s (native bridge enabled)\n", ftdm_channel_state2str(chan->state));
ftdm_set_flag(chan, FTDM_CHANNEL_USER_HANGUP);
goto done;
}
if (chan->state != FTDM_CHANNEL_STATE_DOWN) {
if (chan->state == FTDM_CHANNEL_STATE_HANGUP) {
/* make user's life easier, and just ignore double hangup requests */
@ -2255,6 +2383,8 @@ static ftdm_status_t _ftdm_channel_call_hangup_nl(const char *file, const char *
ftdm_channel_close(&chan);
}
}
done:
return status;
}
@ -2313,6 +2443,39 @@ FT_DECLARE(ftdm_channel_t *) ftdm_span_get_channel(const ftdm_span_t *span, uint
return chan;
}
FT_DECLARE(ftdm_channel_t *) ftdm_span_get_channel_ph(const ftdm_span_t *span, uint32_t chanid)
{
ftdm_channel_t *chan = NULL;
ftdm_channel_t *fchan = NULL;
ftdm_iterator_t *citer = NULL;
ftdm_iterator_t *curr = NULL;
ftdm_mutex_lock(span->mutex);
if (chanid == 0) {
ftdm_mutex_unlock(span->mutex);
return NULL;
}
citer = ftdm_span_get_chan_iterator(span, NULL);
if (!citer) {
ftdm_mutex_unlock(span->mutex);
return NULL;
}
for (curr = citer ; curr; curr = ftdm_iterator_next(curr)) {
fchan = ftdm_iterator_current(curr);
if (fchan->physical_chan_id == chanid) {
chan = fchan;
break;
}
}
ftdm_iterator_free(citer);
ftdm_mutex_unlock(span->mutex);
return chan;
}
FT_DECLARE(uint32_t) ftdm_span_get_chan_count(const ftdm_span_t *span)
{
uint32_t count;
@ -2350,6 +2513,15 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
ftdm_channel_lock(ftdmchan);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) {
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_DEBUG,
"Ignoring indication %s in channel in state %s (native bridge enabled)\n",
ftdm_channel_indication2str(indication),
ftdm_channel_state2str(ftdmchan->state));
status = FTDM_SUCCESS;
goto done;
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IND_ACK_PENDING)) {
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "Cannot indicate %s in channel with indication %s still pending in state %s\n",
ftdm_channel_indication2str(indication),
@ -2450,10 +2622,56 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) ftdm_get_channel_from_string(const char *string_id, ftdm_span_t **out_span, ftdm_channel_t **out_channel)
{
ftdm_status_t status = FTDM_SUCCESS;
int rc = 0;
ftdm_span_t *span = NULL;
ftdm_channel_t *ftdmchan = NULL;
unsigned span_id = 0;
unsigned chan_id = 0;
*out_span = NULL;
*out_channel = NULL;
if (!string_id) {
ftdm_log(FTDM_LOG_ERROR, "Cannot parse NULL channel id string\n");
status = FTDM_EINVAL;
goto done;
}
rc = sscanf(string_id, "%u:%u", &span_id, &chan_id);
if (rc != 2) {
ftdm_log(FTDM_LOG_ERROR, "Failed to parse channel id string '%s'\n", string_id);
status = FTDM_EINVAL;
goto done;
}
status = ftdm_span_find(span_id, &span);
if (status != FTDM_SUCCESS || !span) {
ftdm_log(FTDM_LOG_ERROR, "Failed to find span for channel id string '%s'\n", string_id);
status = FTDM_EINVAL;
goto done;
}
if (chan_id > (FTDM_MAX_CHANNELS_SPAN+1) || !(ftdmchan = span->channels[chan_id])) {
ftdm_log(FTDM_LOG_ERROR, "Invalid channel id string '%s'\n", string_id);
status = FTDM_EINVAL;
goto done;
}
status = FTDM_SUCCESS;
*out_span = span;
*out_channel = ftdmchan;
done:
return status;
}
/* this function MUST be called with the channel lock held with lock recursivity of 1 exactly,
* and the caller must be aware we might unlock the channel for a brief period of time and then lock it again */
static ftdm_status_t _ftdm_channel_call_place_nl(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg)
{
const char *var = NULL;
ftdm_status_t status = FTDM_FAIL;
ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel");
@ -2489,6 +2707,16 @@ static ftdm_status_t _ftdm_channel_call_place_nl(const char *file, const char *f
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED);
ftdm_call_set_call_id(ftdmchan, &ftdmchan->caller_data);
var = ftdm_usrmsg_get_var(usrmsg, "sigbridge_peer");
if (var) {
ftdm_span_t *peer_span = NULL;
ftdm_channel_t *peer_chan = NULL;
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE);
ftdm_get_channel_from_string(var, &peer_span, &peer_chan);
if (peer_chan) {
ftdm_set_flag(peer_chan, FTDM_CHANNEL_NATIVE_SIGBRIDGE);
}
}
/* if the signaling stack left the channel in state down on success, is expecting us to move to DIALING */
if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) {
@ -2544,7 +2772,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_call_place(const char *file, const char *func, i
status = _ftdm_channel_open_by_group(hunting->mode_data.group.group_id,
hunting->mode_data.group.direction, caller_data, &fchan);
} else if (hunting->mode == FTDM_HUNT_CHAN) {
status = _ftdm_channel_open(hunting->mode_data.chan.span_id, hunting->mode_data.chan.chan_id, &fchan);
status = _ftdm_channel_open(hunting->mode_data.chan.span_id, hunting->mode_data.chan.chan_id, &fchan, 0);
} else {
ftdm_log(FTDM_LOG_ERROR, "Cannot make outbound call with invalid hunting mode %d\n", hunting->mode);
return FTDM_EINVAL;
@ -2692,6 +2920,7 @@ static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan)
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_ANSWERED);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_USER_HANGUP);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DIGITAL_MEDIA);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE);
ftdm_mutex_lock(ftdmchan->pre_buffer_mutex);
ftdm_buffer_destroy(&ftdmchan->pre_buffer);
ftdmchan->pre_buffer_size = 0;
@ -4291,7 +4520,7 @@ static struct {
ftdm_io_interface_t *pika_interface;
} interfaces;
static void print_channels_by_flag(ftdm_stream_handle_t *stream, int32_t flagval, int not, int *count)
static void print_channels_by_flag(ftdm_stream_handle_t *stream, ftdm_span_t *inspan, uint32_t inchan_id, int32_t flagval, int not, int *count)
{
ftdm_hash_iterator_t *i = NULL;
ftdm_span_t *span;
@ -4301,40 +4530,147 @@ static void print_channels_by_flag(ftdm_stream_handle_t *stream, int32_t flagval
const void *key = NULL;
void *val = NULL;
uint32_t flag = (1 << flagval);
int mycount = 0;
*count = 0;
ftdm_mutex_lock(globals.mutex);
for (i = hashtable_first(globals.span_hash); i; i = hashtable_next(i)) {
hashtable_this(i, &key, NULL, &val);
if (!key || !val) {
break;
}
span = val;
citer = ftdm_span_get_chan_iterator(span, NULL);
if (inspan) {
citer = ftdm_span_get_chan_iterator(inspan, NULL);
if (!citer) {
continue;
goto end;
}
for (curr = citer ; curr; curr = ftdm_iterator_next(curr)) {
fchan = ftdm_iterator_current(curr);
if (not && !ftdm_test_flag(fchan, flag)) {
stream->write_function(stream, "[s%dc%d][%d:%d] has not flag %d\n",
fchan->span_id, fchan->chan_id,
fchan->physical_span_id, fchan->physical_chan_id,
flagval);
(*count)++;
} else if (!not && ftdm_test_flag(fchan, flag)) {
stream->write_function(stream, "[s%dc%d][%d:%d] has flag %d\n",
fchan->span_id, fchan->chan_id,
fchan->physical_span_id, fchan->physical_chan_id,
flagval);
(*count)++;
if (!inchan_id || inchan_id == fchan->chan_id) {
if (not) {
if (!ftdm_test_flag(fchan, flag)) {
stream->write_function(stream, "[s%dc%d][%d:%d] flag !%d(!%s) ON \n",
fchan->span_id, fchan->chan_id,
fchan->physical_span_id, fchan->physical_chan_id,
flagval, ftdm_val2str(flag, channel_flag_strs, ftdm_array_len(channel_flag_strs), "invalid"));
mycount++;
} else {
stream->write_function(stream, "[s%dc%d][%d:%d] flag !%d(!%s) OFF \n",
fchan->span_id, fchan->chan_id,
fchan->physical_span_id, fchan->physical_chan_id,
flagval, ftdm_val2str(flag, channel_flag_strs, ftdm_array_len(channel_flag_strs), "invalid"));
}
} else {
if (ftdm_test_flag(fchan, flag)) {
stream->write_function(stream, "[s%dc%d][%d:%d] flag %d(%s) ON\n",
fchan->span_id, fchan->chan_id,
fchan->physical_span_id, fchan->physical_chan_id,
flagval, ftdm_val2str(flag, channel_flag_strs, ftdm_array_len(channel_flag_strs), "invalid"));
mycount++;
} else {
stream->write_function(stream, "[s%dc%d][%d:%d] flag %d(%s) OFF \n",
fchan->span_id, fchan->chan_id,
fchan->physical_span_id, fchan->physical_chan_id,
flagval, ftdm_val2str(flag, channel_flag_strs, ftdm_array_len(channel_flag_strs), "invalid"));
}
}
}
}
ftdm_iterator_free(citer);
}
} else {
for (i = hashtable_first(globals.span_hash); i; i = hashtable_next(i)) {
hashtable_this(i, &key, NULL, &val);
if (!key || !val) {
break;
}
span = val;
citer = ftdm_span_get_chan_iterator(span, NULL);
if (!citer) {
continue;
}
for (curr = citer ; curr; curr = ftdm_iterator_next(curr)) {
fchan = ftdm_iterator_current(curr);
if (not && !ftdm_test_flag(fchan, flag)) {
stream->write_function(stream, "[s%dc%d][%d:%d] flag !%d(!%s)\n",
fchan->span_id, fchan->chan_id,
fchan->physical_span_id, fchan->physical_chan_id,
flagval, ftdm_val2str(flag, channel_flag_strs, ftdm_array_len(channel_flag_strs), "invalid"));
mycount++;
} else if (!not && ftdm_test_flag(fchan, flag)) {
stream->write_function(stream, "[s%dc%d][%d:%d] flag %d(%s)\n",
fchan->span_id, fchan->chan_id,
fchan->physical_span_id, fchan->physical_chan_id,
flagval, ftdm_val2str(flag, channel_flag_strs, ftdm_array_len(channel_flag_strs), "invalid"));
mycount++;
}
}
ftdm_iterator_free(citer);
}
}
*count = mycount;
end:
ftdm_mutex_unlock(globals.mutex);
}
static void print_spans_by_flag(ftdm_stream_handle_t *stream, ftdm_span_t *inspan, int32_t flagval, int not, int *count)
{
ftdm_hash_iterator_t *i = NULL;
ftdm_span_t *span;
const void *key = NULL;
void *val = NULL;
uint32_t flag = (1 << flagval);
int mycount = 0;
*count = 0;
ftdm_mutex_lock(globals.mutex);
if (inspan) {
if (not) {
if (!ftdm_test_flag(inspan, flag)) {
stream->write_function(stream, "[s%d] flag !%d(!%s) ON \n",
inspan->span_id,
flagval, ftdm_val2str(flag, span_flag_strs, ftdm_array_len(span_flag_strs), "invalid"));
mycount++;
} else {
stream->write_function(stream, "[s%d] flag !%d(!%s) OFF \n",
inspan->span_id,
flagval, ftdm_val2str(flag, span_flag_strs, ftdm_array_len(span_flag_strs), "invalid"));
}
} else {
if (ftdm_test_flag(inspan, flag)) {
stream->write_function(stream, "[s%d] flag %d(%s) ON \n",
inspan->span_id,
flagval, ftdm_val2str(flag, span_flag_strs, ftdm_array_len(span_flag_strs), "invalid"));
mycount++;
} else {
stream->write_function(stream, "[s%d] flag %d(%s) OFF \n",
inspan->span_id,
flagval, ftdm_val2str(flag, span_flag_strs, ftdm_array_len(span_flag_strs), "invalid"));
}
}
} else {
for (i = hashtable_first(globals.span_hash); i; i = hashtable_next(i)) {
hashtable_this(i, &key, NULL, &val);
if (!key || !val) {
break;
}
span = val;
if (not && !ftdm_test_flag(span, flag)) {
stream->write_function(stream, "[s%d] flag !%d(!%s)\n",
span->span_id,
flagval, ftdm_val2str(flag, span_flag_strs, ftdm_array_len(span_flag_strs), "invalid"));
mycount++;
} else if (!not && ftdm_test_flag(span, flag)) {
stream->write_function(stream, "[s%d] flag %d(%s)\n",
span->span_id,
flagval, ftdm_val2str(flag, span_flag_strs, ftdm_array_len(span_flag_strs), "invalid"));
mycount++;
}
}
}
*count = mycount;
ftdm_mutex_unlock(globals.mutex);
}
@ -4386,12 +4722,52 @@ static void print_core_usage(ftdm_stream_handle_t *stream)
{
stream->write_function(stream,
"--------------------------------------------------------------------------------\n"
"ftdm core state [!]<state_name> - List all channels in or not in the given state\n"
"ftdm core flag <flag-int-value> - List all channels with the given flag value set\n"
"ftdm core state [!]<state-name> - List all channels in or not in the given state\n"
"ftdm core flag [!]<flag-int-value|flag-name> [<span_id|span_name>] [<chan_id>] - List all channels with the given flag value set\n"
"ftdm core spanflag [!]<flag-int-value|flag-name> [<span_id|span_name>] - List all spans with the given span flag value set\n"
"ftdm core calls - List all known calls to the FreeTDM core\n"
"--------------------------------------------------------------------------------\n");
}
static unsigned long long ftdm_str2val(const char *str, val_str_t *val_str_table, ftdm_size_t array_size, unsigned long long default_val)
{
int i;
for (i = 0; i < array_size; i++) {
if (!strcasecmp(val_str_table[i].str, str)) {
return val_str_table[i].val;
}
}
return default_val;
}
static const char *ftdm_val2str(unsigned long long val, val_str_t *val_str_table, ftdm_size_t array_size, const char *default_str)
{
int i;
for (i = 0; i < array_size; i++) {
if (val_str_table[i].val == val) {
return val_str_table[i].str;
}
}
return default_str;
}
static void print_channel_flag_values(ftdm_stream_handle_t *stream)
{
int i;
for (i = 0; i < ftdm_array_len(channel_flag_strs); i++) {
stream->write_function(stream, "%s\n", channel_flag_strs[i].str);
}
}
static void print_span_flag_values(ftdm_stream_handle_t *stream)
{
int i;
for (i = 0; i < ftdm_array_len(span_flag_strs); i++) {
stream->write_function(stream, "%s\n", span_flag_strs[i].str);
}
}
static char *handle_core_command(const char *cmd)
{
char *mycmd = NULL;
@ -4401,11 +4777,12 @@ static char *handle_core_command(const char *cmd)
char *argv[10] = { 0 };
char *state = NULL;
char *flag = NULL;
uint32_t flagval = 0;
unsigned long long flagval = 0;
uint32_t current_call_id = 0;
ftdm_caller_data_t *calldata = NULL;
ftdm_channel_t *fchan = NULL;
ftdm_channel_state_t i = FTDM_CHANNEL_STATE_INVALID;
ftdm_span_t *fspan = NULL;
ftdm_stream_handle_t stream = { 0 };
FTDM_STANDARD_STREAM(stream);
@ -4446,6 +4823,7 @@ static char *handle_core_command(const char *cmd)
print_channels_by_state(&stream, i, not, &count);
stream.write_function(&stream, "\nTotal channels %s %s: %d\n", not ? "not in state" : "in state", ftdm_channel_state2str(i), count);
} else if (!strcasecmp(argv[0], "flag")) {
uint32_t chan_id = 0;
if (argc < 2) {
stream.write_function(&stream, "core flag command requires an argument\n");
print_core_usage(&stream);
@ -4456,9 +4834,77 @@ static char *handle_core_command(const char *cmd)
not = 1;
flag++;
}
flagval = atoi(flag);
print_channels_by_flag(&stream, flagval, not, &count);
if (isalpha(flag[0])) {
flagval = ftdm_str2val(flag, channel_flag_strs, ftdm_array_len(channel_flag_strs), FTDM_CHANNEL_MAX_FLAG);
if (flagval == FTDM_CHANNEL_MAX_FLAG) {
stream.write_function(&stream, "\nInvalid channel flag value. Possible channel flags\n");
print_channel_flag_values(&stream);
goto done;
}
flagval = flagval >> 1;
} else {
flagval = atoi(flag);
}
/* Specific span specified */
if (argv[2]) {
ftdm_span_find_by_name(argv[2], &fspan);
if (!fspan) {
stream.write_function(&stream, "-ERR span:%s not found\n", argv[2]);
goto done;
}
}
/* Specific channel specified */
if (argv[3]) {
chan_id = atoi(argv[3]);
if (chan_id >= ftdm_span_get_chan_count(fspan)) {
stream.write_function(&stream, "-ERR invalid channel %d\n", chan_id);
goto done;
}
}
print_channels_by_flag(&stream, fspan, chan_id, flagval, not, &count);
stream.write_function(&stream, "\nTotal channels %s %d: %d\n", not ? "without flag" : "with flag", flagval, count);
} else if (!strcasecmp(argv[0], "spanflag")) {
if (argc < 2) {
stream.write_function(&stream, "core spanflag command requires an argument\n");
print_core_usage(&stream);
goto done;
}
flag = argv[1];
if (argv[1][0] == '!') {
not = 1;
flag++;
}
if (isalpha(flag[0])) {
flagval = ftdm_str2val(flag, span_flag_strs, ftdm_array_len(span_flag_strs), FTDM_SPAN_MAX_FLAG);
if (flagval == FTDM_SPAN_MAX_FLAG) {
stream.write_function(&stream, "\nInvalid span flag value. Possible span flags\n");
print_span_flag_values(&stream);
goto done;
}
flagval = flagval >> 1;
} else {
flagval = atoi(flag);
}
/* Specific span specified */
if (argv[2]) {
ftdm_span_find_by_name(argv[2], &fspan);
if (!fspan) {
stream.write_function(&stream, "-ERR span:%s not found\n", argv[2]);
goto done;
}
}
print_spans_by_flag(&stream, fspan, flagval, not, &count);
if (!fspan) {
stream.write_function(&stream, "\nTotal spans %s %d: %d\n", not ? "without flag" : "with flag", flagval, count);
}
} else if (!strcasecmp(argv[0], "calls")) {
ftdm_mutex_lock(globals.call_id_mutex);
current_call_id = globals.last_call_id;
@ -4923,14 +5369,15 @@ static ftdm_status_t load_config(void)
} else {
ftdm_log(FTDM_LOG_ERROR, "Invalid cpu alarm set threshold %s\n", val);
}
} else if (!strncasecmp(var, "cpu_reset_alarm_threshold", sizeof("cpu_reset_alarm_threshold")-1)) {
} else if (!strncasecmp(var, "cpu_reset_alarm_threshold", sizeof("cpu_reset_alarm_threshold")-1) ||
!strncasecmp(var, "cpu_clear_alarm_threshold", sizeof("cpu_clear_alarm_threshold")-1)) {
intparam = atoi(val);
if (intparam > 0 && intparam < 100) {
globals.cpu_monitor.reset_alarm_threshold = (uint8_t)intparam;
if (globals.cpu_monitor.reset_alarm_threshold > globals.cpu_monitor.set_alarm_threshold) {
globals.cpu_monitor.reset_alarm_threshold = globals.cpu_monitor.set_alarm_threshold - 10;
ftdm_log(FTDM_LOG_ERROR, "Cpu alarm reset threshold must be lower than set threshold"
", setting threshold to %d\n", globals.cpu_monitor.reset_alarm_threshold);
globals.cpu_monitor.clear_alarm_threshold = (uint8_t)intparam;
if (globals.cpu_monitor.clear_alarm_threshold > globals.cpu_monitor.set_alarm_threshold) {
globals.cpu_monitor.clear_alarm_threshold = globals.cpu_monitor.set_alarm_threshold - 10;
ftdm_log(FTDM_LOG_ERROR, "Cpu alarm clear threshold must be lower than set threshold, "
"setting clear threshold to %d\n", globals.cpu_monitor.clear_alarm_threshold);
}
} else {
ftdm_log(FTDM_LOG_ERROR, "Invalid cpu alarm reset threshold %s\n", val);
@ -5298,16 +5745,68 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_signaling(ftdm_span_t *span, const
return status;
}
static void *ftdm_span_service_events(ftdm_thread_t *me, void *obj)
{
int i;
unsigned waitms;
ftdm_event_t *event;
ftdm_status_t status = FTDM_SUCCESS;
ftdm_span_t *span = (ftdm_span_t*) obj;
short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count);
memset(poll_events, 0, sizeof(short) * span->chan_count);
for(i = 1; i <= span->chan_count; i++) {
poll_events[i] |= FTDM_EVENTS;
}
while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) {
waitms = 1000;
status = ftdm_span_poll_event(span, waitms, poll_events);
switch (status) {
case FTDM_FAIL:
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to poll span for events\n", span->name);
break;
case FTDM_TIMEOUT:
break;
case FTDM_SUCCESS:
/* Check if there are any channels that have events available */
while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS);
break;
default:
ftdm_log(FTDM_LOG_CRIT, "%s:Unhandled IO event\n", span->name);
}
}
return NULL;
}
FT_DECLARE(ftdm_status_t) ftdm_span_register_signal_cb(ftdm_span_t *span, fio_signal_cb_t sig_cb)
{
span->signal_cb = sig_cb;
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) ftdm_span_start(ftdm_span_t *span)
{
ftdm_status_t status = FTDM_FAIL;
ftdm_mutex_lock(span->mutex);
if (ftdm_test_flag(span, FTDM_SPAN_STARTED)) {
status = FTDM_EINVAL;
goto done;
}
if (span->signal_type == FTDM_SIGTYPE_NONE) {
/* If there is no signalling component, start a thread to poll events */
status = ftdm_thread_create_detached(ftdm_span_service_events, span);
if (status != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT,"Failed to start span event monitor thread!\n");
goto done;
}
//ftdm_report_initial_channels_alarms(span);
ftdm_set_flag_locked(span, FTDM_SPAN_STARTED);
goto done;
}
if (!span->start) {
status = FTDM_ENOSYS;
@ -5331,7 +5830,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_start(ftdm_span_t *span)
if (status == FTDM_SUCCESS) {
ftdm_set_flag_locked(span, FTDM_SPAN_STARTED);
}
done:
ftdm_mutex_unlock(span->mutex);
return status;
@ -5516,8 +6014,10 @@ FT_DECLARE(ftdm_status_t) ftdm_group_create(ftdm_group_t **group, const char *na
static ftdm_status_t ftdm_span_trigger_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
{
ftdm_status_t status = span->signal_cb(sigmsg);
return status;
if (!span->signal_cb) {
return FTDM_FAIL;
}
return span->signal_cb(sigmsg);
}
static ftdm_status_t ftdm_span_queue_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
@ -5551,7 +6051,7 @@ static void execute_safety_hangup(void *data)
ftdm_channel_lock(fchan);
fchan->hangup_timer = 0;
if (fchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan(fchan, FTDM_LOG_CRIT, "Forcing hangup since the user did not confirmed our hangup after %dms\n", FORCE_HANGUP_TIMER);
ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Forcing hangup since the user did not confirmed our hangup after %dms\n", FORCE_HANGUP_TIMER);
_ftdm_channel_call_hangup_nl(__FILE__, __FUNCTION__, __LINE__, fchan, NULL);
} else {
ftdm_log_chan(fchan, FTDM_LOG_CRIT, "Not performing safety hangup, channel state is %s\n", ftdm_channel_state2str(fchan->state));
@ -5682,28 +6182,32 @@ static void *ftdm_cpu_monitor_run(ftdm_thread_t *me, void *obj)
{
cpu_monitor_t *monitor = (cpu_monitor_t *)obj;
struct ftdm_cpu_monitor_stats *cpu_stats = ftdm_new_cpu_monitor();
ftdm_log(FTDM_LOG_DEBUG, "CPU monitor thread is now running\n");
if (!cpu_stats) {
return NULL;
goto done;
}
monitor->running = 1;
while(ftdm_running()) {
double time;
if (ftdm_cpu_get_system_idle_time(cpu_stats, &time)) {
while (ftdm_running()) {
double idle_time = 0.0;
int cpu_usage = 0;
if (ftdm_cpu_get_system_idle_time(cpu_stats, &idle_time)) {
break;
}
cpu_usage = (int)(100 - idle_time);
if (monitor->alarm) {
if ((int)time >= (100 - monitor->set_alarm_threshold)) {
ftdm_log(FTDM_LOG_DEBUG, "CPU alarm OFF (idle:%d)\n", (int) time);
if (cpu_usage <= monitor->clear_alarm_threshold) {
ftdm_log(FTDM_LOG_DEBUG, "CPU alarm is now OFF (cpu usage: %d)\n", cpu_usage);
monitor->alarm = 0;
}
if (monitor->alarm_action_flags & FTDM_CPU_ALARM_ACTION_WARN) {
ftdm_log(FTDM_LOG_WARNING, "CPU alarm is ON (cpu usage:%d)\n", (int) (100-time));
} else if (monitor->alarm_action_flags & FTDM_CPU_ALARM_ACTION_WARN) {
ftdm_log(FTDM_LOG_WARNING, "CPU alarm is still ON (cpu usage: %d)\n", cpu_usage);
}
} else {
if ((int)time <= (100-monitor->reset_alarm_threshold)) {
ftdm_log(FTDM_LOG_DEBUG, "CPU alarm ON (idle:%d)\n", (int) time);
if (cpu_usage >= monitor->set_alarm_threshold) {
ftdm_log(FTDM_LOG_WARNING, "CPU alarm is now ON (cpu usage: %d)\n", cpu_usage);
monitor->alarm = 1;
}
}
@ -5712,7 +6216,11 @@ static void *ftdm_cpu_monitor_run(ftdm_thread_t *me, void *obj)
ftdm_delete_cpu_monitor(cpu_stats);
monitor->running = 0;
done:
ftdm_log(FTDM_LOG_DEBUG, "CPU monitor thread is now terminating\n");
return NULL;
#ifdef __WINDOWS__
UNREFERENCED_PARAMETER(me);
#endif
@ -5814,8 +6322,8 @@ FT_DECLARE(ftdm_status_t) ftdm_global_configuration(void)
globals.cpu_monitor.enabled = 0;
globals.cpu_monitor.interval = 1000;
globals.cpu_monitor.alarm_action_flags = 0;
globals.cpu_monitor.set_alarm_threshold = 80;
globals.cpu_monitor.reset_alarm_threshold = 70;
globals.cpu_monitor.set_alarm_threshold = 92;
globals.cpu_monitor.clear_alarm_threshold = 82;
if (load_config() != FTDM_SUCCESS) {
globals.running = 0;
@ -5824,10 +6332,10 @@ FT_DECLARE(ftdm_status_t) ftdm_global_configuration(void)
}
if (globals.cpu_monitor.enabled) {
ftdm_log(FTDM_LOG_INFO, "CPU Monitor is running interval:%d lo-thres:%d hi-thres:%d\n",
ftdm_log(FTDM_LOG_INFO, "CPU Monitor is running interval:%d set-thres:%d clear-thres:%d\n",
globals.cpu_monitor.interval,
globals.cpu_monitor.set_alarm_threshold,
globals.cpu_monitor.reset_alarm_threshold);
globals.cpu_monitor.clear_alarm_threshold);
if (ftdm_cpu_monitor_start() != FTDM_SUCCESS) {
return FTDM_FAIL;

View File

@ -48,9 +48,26 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const c
ftdm_time_t diff = 0;
ftdm_channel_state_t state = fchan->state;
#if 0
/* I could not perform this sanity check without more disruptive changes. Ideally we should check here if the signaling module completing the state
executed a state processor (called ftdm_channel_advance_states() which call fchan->span->state_processor(fchan)) for the state. That is just a
sanity check, as in the past we had at least one bug where the signaling module set the state and then accidentally changed the state to a new one
without calling ftdm_channel_advance_states(), meaning the state processor for the first state was not executed and that lead to unexpected behavior.
If we want to be able to perform this kind of sanity check it would be nice to add a new state status (FTDM_STATE_STATUS_PROCESSING), the function
ftdm_channel_advance_states() would set the state_status to PROCESSING and then the check below for STATUS_NEW would be valid. Currently is not
valid because the signaling module may be completing the state at the end of the state_processor callback and therefore the state will still be
in STATUS_NEW, and is perfectly valid ... */
if (fchan->state_status == FTDM_STATE_STATUS_NEW) {
ftdm_log_chan_ex(fchan, file, func, line, FTDM_LOG_LEVEL_CRIT,
"Asking to complete state change from %s to %s in %llums, but the state is still unprocessed (this might be a bug!)\n",
ftdm_channel_state2str(fchan->last_state), ftdm_channel_state2str(state), diff);
}
#endif
if (fchan->state_status == FTDM_STATE_STATUS_COMPLETED) {
ftdm_assert_return(!ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE), FTDM_FAIL,
"State change flag set but state is not completed\n");
ftdm_assert_return(!ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE), FTDM_FAIL, "State change flag set but state is already completed\n");
return FTDM_SUCCESS;
}
@ -87,6 +104,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const c
ftdm_assert(!fchan->history[hindex].end_time, "End time should be zero!\n");
fchan->history[hindex].end_time = ftdm_current_time_in_ms();
fchan->last_state_change_time = ftdm_current_time_in_ms();
fchan->state_status = FTDM_STATE_STATUS_COMPLETED;
@ -262,6 +280,9 @@ static ftdm_status_t ftdm_core_set_state(const char *file, const char *func, int
}
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) {
goto perform_state_change;
}
if (ftdmchan->span->state_map) {
ok = ftdm_parse_state_map(ftdmchan, state, ftdmchan->span->state_map);
@ -353,6 +374,8 @@ end:
goto done;
}
perform_state_change:
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Changed state from %s to %s\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state));
ftdmchan->last_state = ftdmchan->state;
ftdmchan->state = state;

View File

@ -288,6 +288,7 @@ typedef struct sngisdn_span_data {
uint8_t force_sending_complete;
uint8_t cid_name_method;
uint8_t send_cid_name;
uint8_t send_connect_ack;
int32_t timer_t301;
int32_t timer_t302;
@ -305,7 +306,6 @@ typedef struct sngisdn_span_data {
int32_t timer_t318;
int32_t timer_t319;
int32_t timer_t322;
char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
ftdm_timer_id_t timers[SNGISDN_NUM_SPAN_TIMERS];
ftdm_sched_t *sched;

View File

@ -433,6 +433,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
signal_data->cid_name_method = SNGISDN_CID_NAME_AUTO;
signal_data->send_cid_name = SNGISDN_OPT_DEFAULT;
signal_data->send_connect_ack = SNGISDN_OPT_DEFAULT;
span->default_caller_data.dnis.plan = FTDM_NPI_INVALID;
span->default_caller_data.dnis.type = FTDM_TON_INVALID;
@ -615,6 +616,8 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
parse_timer(val, &signal_data->timer_t322);
} else if (!strcasecmp(var, "trunkgroup")) {
/* Do nothing, we already parsed this parameter */
} else if (!strcasecmp(var, "send-connect-ack")) {
parse_yesno(var, val, &signal_data->send_connect_ack);
} else {
ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
}

View File

@ -738,6 +738,14 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
}
}
if (signal_data->send_connect_ack != SNGISDN_OPT_DEFAULT) {
if (signal_data->send_connect_ack == SNGISDN_OPT_TRUE) {
cfg.t.cfg.s.inDLSAP.ackOpt = TRUE;
} else {
cfg.t.cfg.s.inDLSAP.ackOpt = FALSE;
}
}
/* Override the restart options if user selected that option */
if (signal_data->restart_opt != SNGISDN_OPT_DEFAULT) {
if (signal_data->restart_opt == SNGISDN_OPT_TRUE) {

View File

@ -77,7 +77,9 @@ int ft_to_sngss7_cfg_all(void)
int ret = 0;
/* check if we have done gen_config already */
if (!(g_ftdm_sngss7_data.gen_config)) {
if (g_ftdm_sngss7_data.gen_config == SNG_GEN_CFG_STATUS_INIT) {
/* update the global gen_config so we don't do it again */
g_ftdm_sngss7_data.gen_config = SNG_GEN_CFG_STATUS_PENDING;
/* start of by checking if the license and sig file are valid */
if (sng_validate_license(g_ftdm_sngss7_data.cfg.license,
@ -92,7 +94,7 @@ int ft_to_sngss7_cfg_all(void)
/* set the desired procID value */
sng_set_procId((uint16_t)g_ftdm_sngss7_data.cfg.procId);
}
/* start up the stack manager */
if (sng_isup_init_sm()) {
SS7_CRITICAL("Failed to start Stack Manager\n");
@ -207,30 +209,22 @@ int ft_to_sngss7_cfg_all(void)
}
} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2)) */
/* update the global gen_config so we don't do it again */
g_ftdm_sngss7_data.gen_config = 1;
if(SNG_SS7_OPR_MODE_M2UA_SG == g_ftdm_operating_mode){
if(FTDM_SUCCESS != ftmod_ss7_m2ua_init()){
ftdm_log (FTDM_LOG_ERROR, "ftmod_ss7_m2ua_init FAILED \n");
return FTDM_FAIL;
}
}
g_ftdm_sngss7_data.gen_config = SNG_GEN_CFG_STATUS_DONE;
} /* if (!(g_ftdm_sngss7_data.gen_config)) */
/* go through all the relays channels and configure it */
x = 1;
while (x < (MAX_RELAY_CHANNELS)) {
/* check if this relay channel has been configured already */
if ((g_ftdm_sngss7_data.cfg.relay[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.relay[x].flags & SNGSS7_CONFIGURED))) {
/* send the specific configuration */
if (ftmod_ss7_relay_chan_config(x)) {
SS7_CRITICAL("Relay Channel %d configuration FAILED!\n", x);
return 1;
} else {
SS7_INFO("Relay Channel %d configuration DONE!\n", x);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.relay[x].flags |= SNGSS7_CONFIGURED;
} /* if !SNGSS7_CONFIGURED */
x++;
} /* while (x < (MAX_RELAY_CHANNELS)) */
if (g_ftdm_sngss7_data.gen_config != SNG_GEN_CFG_STATUS_DONE) {
SS7_CRITICAL("General configuration FAILED!\n");
return 1;
}
x = 1;
while (x < (MAX_MTP_LINKS)) {
@ -272,160 +266,203 @@ int ft_to_sngss7_cfg_all(void)
x++;
} /* while (x < (MAX_MTP_LINKS+1)) */
x = 1;
while (x < (MAX_MTP_LINKS)) {
/* check if this link has been configured already */
if ((g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.mtp3Link[x].flags & SNGSS7_CONFIGURED))) {
/* configure mtp3 */
if (ftmod_ss7_mtp3_dlsap_config(x)) {
SS7_CRITICAL("MTP3 DLSAP %d configuration FAILED!\n", x);
return 1;;
} else {
SS7_INFO("MTP3 DLSAP %d configuration DONE!\n", x);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.mtp3Link[x].flags |= SNGSS7_CONFIGURED;
}
x++;
} /* while (x < (MAX_MTP_LINKS+1)) */
x = 1;
while (x < (MAX_NSAPS)) {
/* check if this link has been configured already */
if ((g_ftdm_sngss7_data.cfg.nsap[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.nsap[x].flags & SNGSS7_CONFIGURED))) {
ret = ftmod_ss7_mtp3_nsap_config(x);
if (ret) {
SS7_CRITICAL("MTP3 NSAP %d configuration FAILED!(%s)\n", x, DECODE_LCM_REASON(ret));
return 1;
} else {
SS7_INFO("MTP3 NSAP %d configuration DONE!\n", x);
}
ret = ftmod_ss7_isup_nsap_config(x);
if (ret) {
SS7_CRITICAL("ISUP NSAP %d configuration FAILED!(%s)\n", x, DECODE_LCM_REASON(ret));
return 1;
} else {
SS7_INFO("ISUP NSAP %d configuration DONE!\n", x);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.nsap[x].flags |= SNGSS7_CONFIGURED;
} /* if !SNGSS7_CONFIGURED */
x++;
} /* while (x < (MAX_NSAPS)) */
x = 1;
while (x < (MAX_MTP_LINKSETS+1)) {
/* check if this link has been configured already */
if ((g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags & SNGSS7_CONFIGURED))) {
if (ftmod_ss7_mtp3_linkset_config(x)) {
SS7_CRITICAL("MTP3 LINKSET %d configuration FAILED!\n", x);
return 1;
} else {
SS7_INFO("MTP3 LINKSET %d configuration DONE!\n", x);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags |= SNGSS7_CONFIGURED;
} /* if !SNGSS7_CONFIGURED */
x++;
} /* while (x < (MAX_MTP_LINKSETS+1)) */
x = 1;
while (x < (MAX_MTP_ROUTES+1)) {
/* check if this link has been configured already */
if ((g_ftdm_sngss7_data.cfg.mtpRoute[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.mtpRoute[x].flags & SNGSS7_CONFIGURED))) {
if (ftmod_ss7_mtp3_route_config(x)) {
SS7_CRITICAL("MTP3 ROUTE %d configuration FAILED!\n", x);
return 1;
} else {
SS7_INFO("MTP3 ROUTE %d configuration DONE!\n",x);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.mtpRoute[x].flags |= SNGSS7_CONFIGURED;
} /* if !SNGSS7_CONFIGURED */
x++;
} /* while (x < (MAX_MTP_ROUTES+1)) */
x = 1;
while (x < (MAX_ISAPS)) {
/* check if this link has been configured already */
if ((g_ftdm_sngss7_data.cfg.isap[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.isap[x].flags & SNGSS7_CONFIGURED))) {
if (ftmod_ss7_isup_isap_config(x)) {
SS7_CRITICAL("ISUP ISAP %d configuration FAILED!\n", x);
return 1;
} else {
SS7_INFO("ISUP ISAP %d configuration DONE!\n", x);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.isap[x].flags |= SNGSS7_CONFIGURED;
} /* if !SNGSS7_CONFIGURED */
x++;
} /* while (x < (MAX_ISAPS)) */
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP_STARTED)) {
/* no configs above mtp2 for relay */
if (g_ftdm_sngss7_data.cfg.procId == 1) {
x = 1;
while (x < (MAX_ISUP_INFS)) {
while (x < (MAX_MTP_LINKS)) {
/* check if this link has been configured already */
if ((g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.mtp3Link[x].flags & SNGSS7_CONFIGURED))) {
/* configure mtp3 */
if (ftmod_ss7_mtp3_dlsap_config(x)) {
SS7_CRITICAL("MTP3 DLSAP %d configuration FAILED!\n", x);
return 1;;
} else {
SS7_INFO("MTP3 DLSAP %d configuration DONE!\n", x);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.mtp3Link[x].flags |= SNGSS7_CONFIGURED;
}
x++;
} /* while (x < (MAX_MTP_LINKS+1)) */
/* in M2UA_SG mode there will not be any MTP3 layer */
if(SNG_SS7_OPR_MODE_M2UA_SG != g_ftdm_operating_mode){
x = 1;
while (x < (MAX_NSAPS)) {
/* check if this link has been configured already */
if ((g_ftdm_sngss7_data.cfg.nsap[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.nsap[x].flags & SNGSS7_CONFIGURED))) {
ret = ftmod_ss7_mtp3_nsap_config(x);
if (ret) {
SS7_CRITICAL("MTP3 NSAP %d configuration FAILED!(%s)\n", x, DECODE_LCM_REASON(ret));
return 1;
} else {
SS7_INFO("MTP3 NSAP %d configuration DONE!\n", x);
}
ret = ftmod_ss7_isup_nsap_config(x);
if (ret) {
SS7_CRITICAL("ISUP NSAP %d configuration FAILED!(%s)\n", x, DECODE_LCM_REASON(ret));
return 1;
} else {
SS7_INFO("ISUP NSAP %d configuration DONE!\n", x);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.nsap[x].flags |= SNGSS7_CONFIGURED;
} /* if !SNGSS7_CONFIGURED */
x++;
} /* while (x < (MAX_NSAPS)) */
}
/* in M2UA_SG mode there will not be any MTP3 layer */
if(SNG_SS7_OPR_MODE_M2UA_SG != g_ftdm_operating_mode){
x = 1;
while (x < (MAX_MTP_LINKSETS+1)) {
/* check if this link has been configured already */
if ((g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags & SNGSS7_CONFIGURED))) {
if (ftmod_ss7_mtp3_linkset_config(x)) {
SS7_CRITICAL("MTP3 LINKSET %d configuration FAILED!\n", x);
return 1;
} else {
SS7_INFO("MTP3 LINKSET %d configuration DONE!\n", x);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags |= SNGSS7_CONFIGURED;
} /* if !SNGSS7_CONFIGURED */
x++;
} /* while (x < (MAX_MTP_LINKSETS+1)) */
}
/* in M2UA_SG mode there will not be any MTP3 layer */
if(SNG_SS7_OPR_MODE_M2UA_SG != g_ftdm_operating_mode){
x = 1;
while (x < (MAX_MTP_ROUTES+1)) {
/* check if this link has been configured already */
if ((g_ftdm_sngss7_data.cfg.mtpRoute[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.mtpRoute[x].flags & SNGSS7_CONFIGURED))) {
if (ftmod_ss7_mtp3_route_config(x)) {
SS7_CRITICAL("MTP3 ROUTE %d configuration FAILED!\n", x);
return 1;
} else {
SS7_INFO("MTP3 ROUTE %d configuration DONE!\n",x);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.mtpRoute[x].flags |= SNGSS7_CONFIGURED;
} /* if !SNGSS7_CONFIGURED */
x++;
} /* while (x < (MAX_MTP_ROUTES+1)) */
}
x = 1;
while (x < (MAX_ISAPS)) {
/* check if this link has been configured already */
if ((g_ftdm_sngss7_data.cfg.isupIntf[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.isupIntf[x].flags & SNGSS7_CONFIGURED))) {
if (ftmod_ss7_isup_intf_config(x)) {
SS7_CRITICAL("ISUP INTF %d configuration FAILED!\n", x);
if ((g_ftdm_sngss7_data.cfg.isap[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.isap[x].flags & SNGSS7_CONFIGURED))) {
if (ftmod_ss7_isup_isap_config(x)) {
SS7_CRITICAL("ISUP ISAP %d configuration FAILED!\n", x);
return 1;
} else {
SS7_INFO("ISUP INTF %d configuration DONE!\n", x);
/* set the interface to paused */
sngss7_set_flag(&g_ftdm_sngss7_data.cfg.isupIntf[x], SNGSS7_PAUSED);
SS7_INFO("ISUP ISAP %d configuration DONE!\n", x);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.isupIntf[x].flags |= SNGSS7_CONFIGURED;
g_ftdm_sngss7_data.cfg.isap[x].flags |= SNGSS7_CONFIGURED;
} /* if !SNGSS7_CONFIGURED */
x++;
} /* while (x < (MAX_ISUP_INFS)) */
} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) */
} /* while (x < (MAX_ISAPS)) */
x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
/* check if this link has been configured already */
if ((g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.isupCkt[x].flags & SNGSS7_CONFIGURED))) {
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 */
if ((g_ftdm_sngss7_data.cfg.isupIntf[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.isupIntf[x].flags & SNGSS7_CONFIGURED))) {
if (ftmod_ss7_isup_intf_config(x)) {
SS7_CRITICAL("ISUP INTF %d configuration FAILED!\n", x);
return 1;
} else {
SS7_INFO("ISUP INTF %d configuration DONE!\n", x);
/* set the interface to paused */
sngss7_set_flag(&g_ftdm_sngss7_data.cfg.isupIntf[x], SNGSS7_PAUSED);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.isupIntf[x].flags |= SNGSS7_CONFIGURED;
} /* if !SNGSS7_CONFIGURED */
x++;
} /* while (x < (MAX_ISUP_INFS)) */
} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) */
if (ftmod_ss7_isup_ckt_config(x)) {
SS7_CRITICAL("ISUP CKT %d configuration FAILED!\n", x);
x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
if (g_ftdm_sngss7_data.cfg.procId > 1) {
break;
}
/* check if this link has been configured already */
if ((g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.isupCkt[x].flags & SNGSS7_CONFIGURED))) {
if (ftmod_ss7_isup_ckt_config(x)) {
SS7_CRITICAL("ISUP CKT %d configuration FAILED!\n", x);
return 1;
} else {
SS7_INFO("ISUP CKT %d configuration DONE!\n", x);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.isupCkt[x].flags |= SNGSS7_CONFIGURED;
} /* if !SNGSS7_CONFIGURED */
x++;
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
}
/* go through all the relays channels and configure it */
x = 1;
while (x < (MAX_RELAY_CHANNELS)) {
/* check if this relay channel has been configured already */
if ((g_ftdm_sngss7_data.cfg.relay[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.relay[x].flags & SNGSS7_CONFIGURED))) {
/* send the specific configuration */
if (ftmod_ss7_relay_chan_config(x)) {
SS7_CRITICAL("Relay Channel %d configuration FAILED!\n", x);
return 1;
} else {
SS7_INFO("ISUP CKT %d configuration DONE!\n", x);
SS7_INFO("Relay Channel %d configuration DONE!\n", x);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.isupCkt[x].flags |= SNGSS7_CONFIGURED;
g_ftdm_sngss7_data.cfg.relay[x].flags |= SNGSS7_CONFIGURED;
} /* if !SNGSS7_CONFIGURED */
x++;
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
} /* while (x < (MAX_RELAY_CHANNELS)) */
if(SNG_SS7_OPR_MODE_M2UA_SG == g_ftdm_operating_mode){
return ftmod_ss7_m2ua_cfg();
}
return 0;
}

View File

@ -48,35 +48,7 @@ static int ftmod_ss7_enable_isap(int suId);
static int ftmod_ss7_enable_nsap(int suId);
static int ftmod_ss7_enable_mtpLinkSet(int lnkSetId);
int ftmod_ss7_inhibit_mtp3link(uint32_t id);
int ftmod_ss7_uninhibit_mtp3link(uint32_t id);
int ftmod_ss7_bind_mtp3link(uint32_t id);
int ftmod_ss7_unbind_mtp3link(uint32_t id);
int ftmod_ss7_activate_mtp3link(uint32_t id);
int ftmod_ss7_deactivate_mtp3link(uint32_t id);
int ftmod_ss7_deactivate2_mtp3link(uint32_t id);
int ftmod_ss7_activate_mtplinkSet(uint32_t id);
int ftmod_ss7_deactivate_mtplinkSet(uint32_t id);
int ftmod_ss7_deactivate2_mtplinkSet(uint32_t id);
int ftmod_ss7_lpo_mtp3link(uint32_t id);
int ftmod_ss7_lpr_mtp3link(uint32_t id);
int ftmod_ss7_shutdown_isup(void);
int ftmod_ss7_shutdown_mtp3(void);
int ftmod_ss7_shutdown_mtp2(void);
int ftmod_ss7_shutdown_relay(void);
int ftmod_ss7_disable_relay_channel(uint32_t chanId);
int ftmod_ss7_disable_grp_mtp3Link(uint32_t procId);
int ftmod_ss7_enable_grp_mtp3Link(uint32_t procId);
int ftmod_ss7_disable_grp_mtp2Link(uint32_t procId);
int ftmod_ss7_block_isup_ckt(uint32_t cktId);
int ftmod_ss7_unblock_isup_ckt(uint32_t cktId);
/******************************************************************************/
/* FUNCTIONS ******************************************************************/
@ -88,7 +60,7 @@ int ft_to_sngss7_activate_all(void)
while (x < (MAX_ISAPS)) {
/* check if this link has already been actived */
if ((g_ftdm_sngss7_data.cfg.isap[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.isap[x].flags & SNGSS7_ACTIVE))) {
(!(g_ftdm_sngss7_data.cfg.isap[x].flags & SNGSS7_ACTIVE))) {
if (ftmod_ss7_enable_isap(x)) {
SS7_CRITICAL("ISAP %d Enable: NOT OK\n", x);
@ -100,15 +72,16 @@ int ft_to_sngss7_activate_all(void)
/* set the SNGSS7_ACTIVE flag */
g_ftdm_sngss7_data.cfg.isap[x].flags |= SNGSS7_ACTIVE;
} /* if !SNGSS7_ACTIVE */
x++;
} /* while (x < (MAX_ISAPS)) */
if(SNG_SS7_OPR_MODE_M2UA_SG != g_ftdm_operating_mode){
x = 1;
while (x < (MAX_NSAPS)) {
/* check if this link has already been actived */
if ((g_ftdm_sngss7_data.cfg.nsap[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.nsap[x].flags & SNGSS7_ACTIVE))) {
(!(g_ftdm_sngss7_data.cfg.nsap[x].flags & SNGSS7_ACTIVE))) {
if (ftmod_ss7_enable_nsap(x)) {
SS7_CRITICAL("NSAP %d Enable: NOT OK\n", x);
@ -120,30 +93,35 @@ int ft_to_sngss7_activate_all(void)
/* set the SNGSS7_ACTIVE flag */
g_ftdm_sngss7_data.cfg.nsap[x].flags |= SNGSS7_ACTIVE;
} /* if !SNGSS7_ACTIVE */
x++;
} /* while (x < (MAX_NSAPS)) */
if (g_ftdm_sngss7_data.cfg.mtpRoute[1].id != 0) {
x = 1;
while (x < (MAX_MTP_LINKSETS+1)) {
/* check if this link has already been actived */
if ((g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags & SNGSS7_ACTIVE))) {
if (ftmod_ss7_enable_mtpLinkSet(x)) {
SS7_CRITICAL("LinkSet \"%s\" Enable: NOT OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name);
return 1;
} else {
SS7_INFO("LinkSet \"%s\" Enable: OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name);
}
/* set the SNGSS7_ACTIVE flag */
g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags |= SNGSS7_ACTIVE;
} /* if !SNGSS7_ACTIVE */
x++;
} /* while (x < (MAX_MTP_LINKSETS+1)) */
if (g_ftdm_sngss7_data.cfg.mtpRoute[1].id != 0) {
x = 1;
while (x < (MAX_MTP_LINKSETS+1)) {
/* check if this link has already been actived */
if ((g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) &&
(!(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags & SNGSS7_ACTIVE))) {
if (ftmod_ss7_enable_mtpLinkSet(x)) {
SS7_CRITICAL("LinkSet \"%s\" Enable: NOT OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name);
return 1;
} else {
SS7_INFO("LinkSet \"%s\" Enable: OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name);
}
/* set the SNGSS7_ACTIVE flag */
g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags |= SNGSS7_ACTIVE;
} /* if !SNGSS7_ACTIVE */
x++;
} /* while (x < (MAX_MTP_LINKSETS+1)) */
}
}
if(SNG_SS7_OPR_MODE_M2UA_SG == g_ftdm_operating_mode){
return ftmod_ss7_m2ua_start();
}
return 0;
@ -779,7 +757,14 @@ int ftmod_ss7_disable_grp_mtp3Link(uint32_t procId)
cntrl.t.cntrl.action = AUBND_DIS; /* disable and unbind */
cntrl.t.cntrl.subAction = SAGR_DSTPROCID; /* specificed element */
return (sng_cntrl_mtp3(&pst, &cntrl));
if (g_ftdm_sngss7_data.cfg.procId == procId) {
SS7_DEBUG("Executing MTP3 cntrl command local pid =%i\n",procId);
return (sng_cntrl_mtp3(&pst, &cntrl));
} else {
SS7_WARN("Executing MTP3 cntrl command different local=%i target=%i\n",
g_ftdm_sngss7_data.cfg.procId,procId);
return (sng_cntrl_mtp3_nowait(&pst, &cntrl));
}
}
@ -811,7 +796,14 @@ int ftmod_ss7_enable_grp_mtp3Link(uint32_t procId)
cntrl.t.cntrl.action = ABND_ENA; /* bind and enable */
cntrl.t.cntrl.subAction = SAGR_DSTPROCID; /* specificed element */
return (sng_cntrl_mtp3(&pst, &cntrl));
if (g_ftdm_sngss7_data.cfg.procId == procId) {
SS7_DEBUG("Executing MTP3 cntrl command local pid =%i\n",procId);
return (sng_cntrl_mtp3(&pst, &cntrl));
} else {
SS7_WARN("Executing MTP3 cntrl command different local=%i target=%i\n",
g_ftdm_sngss7_data.cfg.procId,procId);
return (sng_cntrl_mtp3_nowait(&pst, &cntrl));
}
}
@ -848,7 +840,7 @@ int ftmod_ss7_disable_grp_mtp2Link(uint32_t procId)
}
/******************************************************************************/
int ftmod_ss7_block_isup_ckt(uint32_t cktId)
int __ftmod_ss7_block_isup_ckt(uint32_t cktId, ftdm_bool_t wait)
{
SiMngmt cntrl;
Pst pst;
@ -876,7 +868,11 @@ int ftmod_ss7_block_isup_ckt(uint32_t cktId)
cntrl.t.cntrl.action = ADISIMM; /* block via BLO */
cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */
return (sng_cntrl_isup(&pst, &cntrl));
if (wait == FTDM_TRUE) {
return (sng_cntrl_isup(&pst, &cntrl));
} else {
return (sng_cntrl_isup_nowait(&pst, &cntrl));
}
}
/******************************************************************************/

View File

@ -33,6 +33,7 @@
* Contributors:
*
* Ricardo Barroetaveña <rbarroetavena@anura.com.ar>
* James Zhang <jzhang@sangoma.com>
*
*/
@ -87,6 +88,8 @@ ftdm_status_t handle_olm_msg(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* FUNCTIONS ******************************************************************/
#define ftdm_running_return(var) if (!ftdm_running()) { SS7_ERROR("Error: ftdm_running is not set! Ignoring\n"); return var; }
ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
@ -94,9 +97,11 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
char var[FTDM_DIGITS_LIMIT];
memset(var, '\0', sizeof(var));
ftdm_running_return(FTDM_FAIL);
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
@ -118,11 +123,24 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* as per Q.764, 2.8.2.3 xiv ... remove the block from this channel */
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);
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_MN_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX_DN);
/* KONRAD FIX ME : check in case there is a ckt and grp block */
}
sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_TX);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_SENT);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_RX);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_RX_DN);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_TX);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_SENT);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_RX);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_RX_DN);
sngss7_clear_ckt_flag(sngss7_info, FLAG_FULL_NUMBER);
/* check whether the ftdm channel is in a state to accept a call */
switch (ftdmchan->state) {
@ -167,6 +185,12 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* fill in ANI */
ftdm_set_string(ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.cid_num.digits);
}
else {
if (g_ftdm_sngss7_data.cfg.force_inr) {
sngss7_set_ckt_flag(sngss7_info, FLAG_INR_TX);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_SENT);
}
}
if (siConEvnt->cgPtyNum.scrnInd.pres) {
/* fill in the screening indication value */
@ -178,6 +202,11 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
ftdmchan->caller_data.pres = siConEvnt->cgPtyNum.presRest.val;
}
} else {
if (g_ftdm_sngss7_data.cfg.force_inr) {
sngss7_set_ckt_flag(sngss7_info, FLAG_INR_TX);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_SENT);
}
SS7_INFO_CHAN(ftdmchan,"No Calling party (ANI) information in IAM!%s\n", " ");
}
@ -192,12 +221,16 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
} else {
SS7_INFO_CHAN(ftdmchan,"No Called party (DNIS) information in IAM!%s\n", " ");
}
copy_NatureOfConnection_from_sngss7(ftdmchan, &siConEvnt->natConInd);
copy_fwdCallInd_hex_from_sngss7(ftdmchan, &siConEvnt->fwdCallInd);
copy_access_transport_from_sngss7(ftdmchan, &siConEvnt->accTrnspt);
copy_ocn_from_sngss7(ftdmchan, &siConEvnt->origCdNum);
copy_redirgNum_from_sngss7(ftdmchan, &siConEvnt->redirgNum);
copy_redirgInfo_from_sngss7(ftdmchan, &siConEvnt->redirInfo);
copy_genNmb_from_sngss7(ftdmchan, &siConEvnt->genNmb);
copy_cgPtyCat_from_sngss7(ftdmchan, &siConEvnt->cgPtyCat);
copy_cdPtyNum_from_sngss7(ftdmchan, &siConEvnt->cdPtyNum);
/* fill in the TMR/bearer capability */
if (siConEvnt->txMedReq.eh.pres) {
@ -213,9 +246,6 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sprintf(var, "%d", siConEvnt->cgPtyNum.natAddrInd.val);
sngss7_add_var(sngss7_info, "ss7_clg_nadi", var);
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) {
@ -247,7 +277,8 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
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 );
sprintf(var, "%d", g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].dpc );
sngss7_add_var(sngss7_info, "ss7_opc", var);
if (siConEvnt->callRef.callId.pres) {
@ -308,24 +339,26 @@ handle_glare:
/* setup the hangup cause */
ftdmchan->caller_data.hangup_cause = 34; /* Circuit Congrestion */
/* this is a remote hangup request */
sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL);
/* move the state of the channel to Terminating to end the call */
/* move the state of the channel to Terminating to end the call
in TERMINATING state, the release cause is set to REMOTE_REL
in any means. So we don't have to set the release reason here.
*/
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
} /* if (!(sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE))) */
}
break;
/**************************************************************************/
default: /* should not have gotten an IAM while in this state */
SS7_ERROR_CHAN(ftdmchan, "Got IAM on channel in invalid state(%s)...reset!\n", ftdm_channel_state2str (ftdmchan->state));
/* reset the cic */
sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX);
/* move the state of the channel to RESTART to force a reset */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
/* throw the TX reset flag */
if (!sngss7_tx_reset_status_pending(sngss7_info)) {
sngss7_tx_reset_restart(sngss7_info);
sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL);
/* go to RESTART */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
}
break;
/**************************************************************************/
} /* switch (ftdmchan->state) */
@ -344,6 +377,8 @@ ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sngss7_chan_data_t *sngss7_info ;
ftdm_channel_t *ftdmchan;
ftdm_running_return(FTDM_FAIL);
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
@ -389,11 +424,14 @@ ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circ
SS7_ERROR_CHAN(ftdmchan, "RX ACM in invalid state :%s...resetting CIC\n",
ftdm_channel_state2str (ftdmchan->state));
/* reset the cic */
sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX);
/* throw the TX reset flag */
if (!sngss7_tx_reset_status_pending(sngss7_info)) {
sngss7_tx_reset_restart(sngss7_info);
sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL);
/* go to RESTART */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
/* go to RESTART */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
}
break;
/**********************************************************************/
} /* switch (ftdmchan->state) */
@ -422,10 +460,26 @@ ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/**************************************************************************/
case (INFORMATION):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx INF\n", sngss7_info->circuit->cic);
SS7_DEBUG_CHAN (ftdmchan, "Cancelling T.39 timer %s\n", " ");
/* check if t39 is active */
if (sngss7_info->t39.hb_timer_id) {
ftdm_sched_cancel_timer (sngss7_info->t39.sched, sngss7_info->t39.hb_timer_id);
SS7_DEBUG_CHAN (ftdmchan, "T.39 timer has been cancelled upon receiving INF message %s\n", " ");
}
sngss7_set_ckt_flag(sngss7_info, FLAG_INF_RX_DN);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
break;
/**************************************************************************/
case (INFORMATREQ):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx INR\n", sngss7_info->circuit->cic);
ft_to_sngss7_inf(ftdmchan, siCnStEvnt);
sngss7_set_ckt_flag(sngss7_info, FLAG_INR_RX);
break;
/**************************************************************************/
case (SUBSADDR):
@ -599,6 +653,8 @@ ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sngss7_chan_data_t *sngss7_info ;
ftdm_channel_t *ftdmchan;
ftdm_running_return(FTDM_FAIL);
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
@ -651,10 +707,13 @@ ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circ
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx ANM/CON\n", sngss7_info->circuit->cic);
/* throw the TX reset flag */
sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX);
if (!sngss7_tx_reset_status_pending(sngss7_info)) {
sngss7_tx_reset_restart(sngss7_info);
sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL);
/* go to RESTART */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
/* go to RESTART */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
}
break;
/**************************************************************************/
@ -674,6 +733,8 @@ ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sngss7_chan_data_t *sngss7_info ;
ftdm_channel_t *ftdmchan;
ftdm_running_return(FTDM_FAIL);
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
@ -750,6 +811,10 @@ ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* send out the release complete */
ft_to_sngss7_rlc (ftdmchan);
} else {
SS7_DEBUG_CHAN(ftdmchan, "Collision of REL messages - resetting state.\n", " ");
ft_to_sngss7_rlc (ftdmchan);
goto rel_ind_reset;
}
break;
/**************************************************************************/
@ -772,11 +837,15 @@ ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/**************************************************************************/
default:
/* throw the reset flag */
sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_RX);
rel_ind_reset:
/* throw the TX reset flag */
if (!sngss7_tx_reset_status_pending(sngss7_info)) {
sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL);
sngss7_tx_reset_restart(sngss7_info);
/* set the state to RESTART */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
/* go to RESTART */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
}
break;
/**************************************************************************/
} /* switch (ftdmchan->state) */
@ -796,6 +865,8 @@ ftdm_status_t handle_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sngss7_chan_data_t *sngss7_info ;
ftdm_channel_t *ftdmchan;
ftdm_running_return(FTDM_FAIL);
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
@ -847,6 +918,8 @@ ftdm_status_t handle_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sngss7_chan_data_t *sngss7_info ;
ftdm_channel_t *ftdmchan;
ftdm_running_return(FTDM_FAIL);
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
@ -874,6 +947,8 @@ ftdm_status_t handle_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sngss7_chan_data_t *sngss7_info ;
ftdm_channel_t *ftdmchan;
ftdm_running_return(FTDM_FAIL);
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
@ -901,6 +976,8 @@ ftdm_status_t handle_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sngss7_chan_data_t *sngss7_info ;
ftdm_channel_t *ftdmchan;
ftdm_running_return(FTDM_FAIL);
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
@ -928,6 +1005,8 @@ ftdm_status_t handle_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t cir
sngss7_chan_data_t *sngss7_info ;
ftdm_channel_t *ftdmchan;
ftdm_running_return(FTDM_FAIL);
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
@ -955,6 +1034,8 @@ ftdm_status_t handle_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t cir
sngss7_chan_data_t *sngss7_info ;
ftdm_channel_t *ftdmchan;
ftdm_running_return(FTDM_FAIL);
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
@ -982,6 +1063,8 @@ ftdm_status_t handle_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t cir
sngss7_chan_data_t *sngss7_info ;
ftdm_channel_t *ftdmchan;
ftdm_running_return(FTDM_FAIL);
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
@ -1006,6 +1089,8 @@ ftdm_status_t handle_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t cir
ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_running_return(FTDM_FAIL);
/* 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)) {
@ -1098,11 +1183,12 @@ ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
break;
/**************************************************************************/
case SIT_STA_CGBRSP: /* mntc. oriented CGB response */
/*handle_cgb_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);*/
SS7_INFO(" Rx CGBA \n");
break;
/**************************************************************************/
case SIT_STA_CGURSP: /* mntc. oriented CGU response */
/*SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));*/
SS7_INFO(" Rx CGUA \n");
break;
/**************************************************************************/
case SIT_STA_GRSREQ: /* circuit group reset request */
@ -1206,6 +1292,8 @@ ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t ci
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
ftdm_running_return(FTDM_FAIL);
/* confirm that the circuit is voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@ -1235,6 +1323,7 @@ ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t ci
/* the glare flag is already up so it was caught ... do nothing */
SS7_DEBUG_CHAN(ftdmchan, "Glare flag is already up...nothing to do!%s\n", " ");
} else {
int bHangup = 0;
SS7_DEBUG_CHAN(ftdmchan, "Glare flag is not up yet...indicating glare from reattempt!%s\n", " ");
/* glare, throw the flag */
sngss7_set_ckt_flag(sngss7_info, FLAG_GLARE);
@ -1242,14 +1331,45 @@ ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t ci
/* clear any existing glare data from the channel */
memset(&sngss7_info->glare, 0x0, sizeof(sngss7_glare_data_t));
if (g_ftdm_sngss7_data.cfg.glareResolution == SNGSS7_GLARE_DOWN) {
/* If I'm in DOWN mode, I will always hangup my call. */
bHangup = 1;
}
else if (g_ftdm_sngss7_data.cfg.glareResolution == SNGSS7_GLARE_PC) {
/* I'm in PointCode mode.
Case 1: My point code is higher than the other side.
If the CIC number is even, I'm trying to control.
If the CIC number is odd, I'll hangup my call and back off.
Case 2: My point code is lower than the other side.
If the CIC number is odd, I'm trying to control.
If the CIC number is even, I'll hangup my call and back off.
*/
if( g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].spc > g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].dpc )
{
if ((sngss7_info->circuit->cic % 2) == 1 ) {
bHangup = 1;
}
} else {
if( (sngss7_info->circuit->cic % 2) == 0 ) {
bHangup = 1;
}
}
}
else {
/* If I'm in CONTROL mode, I will not hangup my call. */
bHangup = 0;
}
if (bHangup) {
/* setup the hangup cause */
ftdmchan->caller_data.hangup_cause = 34; /* Circuit Congrestion */
/* this is a remote hangup request */
sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL);
/* move the state of the channel to Terminating to end the call */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
/* move the state of the channel to Terminating to end the call
in TERMINATING state, the release cause is set to REMOTE_REL
in any means. So we don't have to set the release reason here.
*/
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
}
}
/* unlock the channel again before we exit */
@ -1269,6 +1389,8 @@ ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circui
int infId;
int i;
ftdm_running_return(FTDM_FAIL);
/* extract the affected infId from the circuit structure */
infId = g_ftdm_sngss7_data.cfg.isupCkt[circuit].infId;
@ -1333,6 +1455,8 @@ ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circu
ftdm_channel_t *ftdmchan = NULL;
int infId;
int i;
ftdm_running_return(FTDM_FAIL);
/* extract the affect infId from the circuit structure */
infId = g_ftdm_sngss7_data.cfg.isupCkt[circuit].infId;
@ -1397,6 +1521,8 @@ ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t ci
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
ftdm_running_return(FTDM_FAIL);
/* confirm that the circuit is voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@ -1452,6 +1578,8 @@ ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t cir
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
ftdm_running_return(FTDM_FAIL);
/* confirm that the circuit is voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@ -1497,6 +1625,8 @@ ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit,
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
ftdm_running_return(FTDM_FAIL);
/* confirm that the circuit is voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@ -1565,6 +1695,8 @@ ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
ftdm_running_return(FTDM_FAIL);
/* confirm that the circuit is voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@ -1597,6 +1729,7 @@ ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* throw the ckt block flag */
sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN);
/* set the channel to suspended state */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
@ -1615,6 +1748,8 @@ ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
ftdm_running_return(FTDM_FAIL);
/* confirm that the circuit is voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@ -1656,6 +1791,8 @@ ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
ftdm_running_return(FTDM_FAIL);
/* confirm that the circuit is voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@ -1744,6 +1881,8 @@ ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
ftdm_running_return(FTDM_FAIL);
/* confirm that the circuit is voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@ -1784,6 +1923,7 @@ ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
default:
/* set the state of the channel to restart...the rest is done by the chan monitor */
sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
/**************************************************************************/
@ -1803,6 +1943,8 @@ ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
ftdm_running_return(FTDM_FAIL);
/* confirm that the circuit is voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@ -1861,6 +2003,8 @@ ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
ftdm_running_return(FTDM_FAIL);
/* confirm that the circuit is voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@ -1917,7 +2061,7 @@ ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP);
/* go to DOWN */
/*ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);*/
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
/**********************************************************************/
@ -1951,6 +2095,8 @@ ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
ftdm_channel_t *ftdmchan = NULL;
sngss7_span_data_t *sngss7_span = NULL;
int range = 0;
ftdm_running_return(FTDM_FAIL);
/* confirm that the circuit is voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@ -2008,6 +2154,8 @@ ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
ftdm_channel_t *ftdmchan = NULL;
sngss7_span_data_t *sngss7_span = NULL;
int range = 0;
ftdm_running_return(FTDM_FAIL);
/* confirm that the circuit is voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@ -2072,6 +2220,8 @@ ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t ci
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
ftdm_running_return(FTDM_FAIL);
/* confirm that the circuit is voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@ -2122,6 +2272,8 @@ ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t ci
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
ftdm_running_return(FTDM_FAIL);
/* confirm that the circuit is voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@ -2177,6 +2329,7 @@ ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit
sngss7_span_data_t *sngss7_span = NULL;
ftdm_channel_t *ftdmchan = NULL;
ftdm_running_return(FTDM_FAIL);
/* confirm that the circuit is voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {
@ -2215,6 +2368,8 @@ ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit
cinfo->ucic.range = cinfo->tx_grs.range;
ftdm_set_flag(sngss7_span, SNGSS7_UCIC_PENDING);
SS7_WARN("Set span SNGSS7_UCIC_PENDING for ISUP circuit = %d!\n", circuit);
ftdm_channel_unlock(fchan);
goto done;
@ -2227,6 +2382,7 @@ ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit
ftdm_mutex_lock(ftdmchan->mutex);
/* throw the ckt block flag */
SS7_DEBUG("Set FLAG_CKT_UCIC_BLOCK for ISUP circuit = %d!\n", circuit);
sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK);
/* set the channel to suspended state */
@ -2256,7 +2412,10 @@ ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
int blockType = 0;
int byte = 0;
int bit = 0;
int x;
int x;
int loop_range=0;
ftdm_running_return(FTDM_FAIL);
memset(&status[0], '\0', sizeof(status));
@ -2321,61 +2480,56 @@ ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
}
/* loop over the cics starting from circuit until range+1 */
for (x = circuit; x < (circuit + range + 1); x++) {
/* confirm this is a voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type != SNG_CKT_VOICE) continue;
/* grab the circuit in question */
if (extract_chan_data(x, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x);
break;
loop_range = circuit + range + 1;
x = circuit;
while( x < loop_range ) {
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type != SNG_CKT_VOICE) {
loop_range++;
}
/* lock the channel */
ftdm_mutex_lock(ftdmchan->mutex);
else {
if (extract_chan_data(x, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x);
} else {
ftdm_mutex_lock(ftdmchan->mutex);
if (status[byte] & (1 << bit)) {
switch (blockType) {
/**********************************************************************/
case 0: /* maintenance oriented */
sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
break;
/**********************************************************************/
case 1: /* hardware failure oriented */
sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
break;
/**********************************************************************/
case 2: /* reserved for national use */
break;
/**********************************************************************/
default:
break;
/**********************************************************************/
}
}
#if 0
SS7_ERROR("KONRAD -> circuit=%d, byte=%d, bit=%d, status[byte]=%d, math=%d\n",
x,
byte,
bit,
status[byte],
(status[byte] & (1 << bit)));
#endif
if (status[byte] & (1 << bit)) {
switch (blockType) {
/**********************************************************************/
case 0: /* maintenance oriented */
sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
break;
/**********************************************************************/
case 1: /* hardware failure oriented */
sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
break;
/**********************************************************************/
case 2: /* reserved for national use */
break;
/**********************************************************************/
default:
break;
/**********************************************************************/
} /* switch (blockType) */
/* bring the sig status down */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
/* unlock the channel again before we exit */
ftdm_mutex_unlock(ftdmchan->mutex);
/* update the bit and byte counter*/
bit ++;
if (bit == 8) {
byte++;
bit = 0;
}
}
}
x++;
}
/* bring the sig status down */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN);
/* unlock the channel again before we exit */
ftdm_mutex_unlock(ftdmchan->mutex);
/* update the bit and byte counter*/
bit ++;
if (bit == 8) {
byte++;
bit = 0;
}
} /* for (x = circuit; x < (circuit + range + 1); x++) */
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
@ -2402,8 +2556,11 @@ ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
int blockType = 0;
int byte = 0;
int bit = 0;
int x;
int x;
int loop_range=0;
ftdm_sigmsg_t sigev;
ftdm_running_return(FTDM_FAIL);
memset(&sigev, 0, sizeof (sigev));
memset(&status[0], '\0', sizeof(status));
@ -2470,57 +2627,62 @@ ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
}
/* loop over the cics starting from circuit until range+1 */
for (x = circuit; x < (circuit + range + 1); x++) {
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type != SNG_CKT_VOICE) continue;
/* grab the circuit in question */
if (extract_chan_data(x, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x);
break;
loop_range = circuit + range + 1;
x = circuit;
while( x < loop_range ) {
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type != SNG_CKT_VOICE) {
loop_range++;
} else {
if (extract_chan_data(x, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x);
}
else {
ftdm_mutex_lock(ftdmchan->mutex);
if (status[byte] & (1 << bit)) {
switch (blockType) {
/**********************************************************************/
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 */
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
break;
/**********************************************************************/
case 2: /* reserved for national use */
break;
/**********************************************************************/
default:
break;
/**********************************************************************/
} /* switch (blockType) */
} /* if (status[byte] & (1 << bit)) */
sigev.chan_id = ftdmchan->chan_id;
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
/* bring the sig status down */
if (sngss7_channel_status_clear(sngss7_info)) {
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
}
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
ftdm_mutex_unlock(ftdmchan->mutex);
/* update the bit and byte counter*/
bit ++;
if (bit == 8) {
byte++;
bit = 0;
}
}
}
/* lock the channel */
ftdm_mutex_lock(ftdmchan->mutex);
if (status[byte] & (1 << bit)) {
switch (blockType) {
/**********************************************************************/
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 */
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
break;
/**********************************************************************/
case 2: /* reserved for national use */
break;
/**********************************************************************/
default:
break;
/**********************************************************************/
} /* switch (blockType) */
} /* if (status[byte] & (1 << bit)) */
sigev.chan_id = ftdmchan->chan_id;
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
/* bring the sig status down */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
/* unlock the channel again before we exit */
ftdm_mutex_unlock(ftdmchan->mutex);
/* update the bit and byte counter*/
bit ++;
if (bit == 8) {
byte++;
bit = 0;
}
} /* for (x = circuit; x < (circuit + range + 1); x++) */
x++;
}
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
@ -2541,6 +2703,8 @@ ftdm_status_t handle_olm_msg(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
ftdm_running_return(FTDM_FAIL);
/* confirm that the circuit is voice channel */
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) {

View File

@ -81,6 +81,7 @@ void sngss7_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCo
/* initalize the sngss7_event */
sngss7_event = ftdm_malloc(sizeof(*sngss7_event));
if (sngss7_event == NULL) {
SS7_ERROR("Failed to allocate memory for sngss7_event!\n");
SS7_FUNC_TRACE_EXIT(__FUNCTION__);

View File

@ -114,6 +114,7 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
{
char buf[50];
int x = 1;
int log_level = FTDM_LOG_LEVEL_DEBUG;
memset(buf, '\0', sizeof(buf));
@ -158,11 +159,22 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
break;
case (LCM_CAUSE_UNKNOWN):
default:
ftdm_log(FTDM_LOG_DEBUG,"[MTP2]%s cause:%s event:%s\n",
buf,
DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
DECODE_LSD_EVENT(sta->t.usta.alarm.event));
break;
{
if ((LSD_EVENT_ALIGN_LOST == sta->t.usta.alarm.event) ||
(LSD_EVENT_PROT_ST_DN == sta->t.usta.alarm.event)) {
log_level = FTDM_LOG_LEVEL_WARNING;
} else if ((LSD_EVENT_LINK_ALIGNED == sta->t.usta.alarm.event) ||
(LSD_EVENT_PROT_ST_UP == sta->t.usta.alarm.event)){
log_level = FTDM_LOG_LEVEL_INFO;
} else {
log_level = FTDM_LOG_LEVEL_WARNING;
}
ftdm_log(FTDM_PRE, log_level,"[MTP2]%s cause:%s event:%s\n",
buf,
DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
DECODE_LSD_EVENT(sta->t.usta.alarm.event));
break;
}
/******************************************************************/
} /* switch (sta->t.usta.alarm.cause) */
break;
@ -184,7 +196,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 : %s\n",
ftdm_log(FTDM_LOG_WARNING,"[MTP2]%s %s : %s\n",
buf,
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_LSD_CAUSE(sta->t.usta.alarm.cause));
@ -207,7 +219,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_DEBUG,"[MTP2]%s %s : %s\n",
ftdm_log(FTDM_LOG_WARNING,"[MTP2]%s %s : %s\n",
buf,
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_DISC_REASON(sta->t.usta.evntParm[1]));
@ -231,7 +243,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 : RTB Queue Len(%d)|Oldest BSN(%d)|Tx Queue Len(%d)|Outstanding Frames(%d)\n",
ftdm_log(FTDM_LOG_WARNING,"[MTP2]%s %s : RTB Queue Len(%d)|Oldest BSN(%d)|Tx Queue Len(%d)|Outstanding Frames(%d)\n",
buf,
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
sta->t.usta.evntParm[1],
@ -257,7 +269,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 : RTB Queue Len(%d)\n",
ftdm_log(FTDM_LOG_WARNING,"[MTP2]%s %s : RTB Queue Len(%d)\n",
buf,
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
sta->t.usta.evntParm[1]);
@ -280,7 +292,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 : %s\n",
ftdm_log(FTDM_LOG_WARNING,"[MTP2]%s %s : %d\n",
buf,
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_DISC_REASON(sta->t.usta.evntParm[1]));
@ -288,7 +300,7 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
/**********************************************************************/
case (LCM_EVENT_UI_INV_EVT):
case (LCM_EVENT_LI_INV_EVT):
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s(%d) : %s(%d) : Primitive (%d)\n",
ftdm_log(FTDM_LOG_WARNING,"[MTP2] %s(%d) : %s(%d) : Primitive (%d)\n",
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
sta->t.usta.alarm.event,
DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
@ -302,14 +314,14 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
/******************************************************************/
case (LCM_CAUSE_UNKNOWN):
case (LCM_CAUSE_SWVER_NAVAIL):
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s : %s : Event (%d)\n",
ftdm_log(FTDM_LOG_WARNING,"[MTP2] %s : %s : Event (%d)\n",
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.evntParm[0]);
break;
/******************************************************************/
case (LCM_CAUSE_DECODE_ERR):
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s : %s : Primitive (%d)|Version (%d)\n",
ftdm_log(FTDM_LOG_WARNING,"[MTP2] %s : %s : Primitive (%d)|Version (%d)\n",
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.evntParm[0],
@ -317,7 +329,7 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
break;
/******************************************************************/
default:
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s(%d) : %s(%d)\n",
ftdm_log(FTDM_LOG_WARNING,"[MTP2] %s(%d) : %s(%d)\n",
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
sta->t.usta.alarm.event,
DECODE_LSD_CAUSE(sta->t.usta.alarm.cause),
@ -328,7 +340,7 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
break;
/**********************************************************************/
default:
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s(%d) : %s(%d)\n",
ftdm_log(FTDM_LOG_WARNING,"[MTP2] %s(%d) : %s(%d)\n",
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
sta->t.usta.alarm.event,
DECODE_LSD_CAUSE(sta->t.usta.alarm.cause),
@ -381,7 +393,7 @@ void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta)
/**********************************************************************/
case (LSN_EVENT_INV_OPC_OTHER_END):
ftdm_log(FTDM_LOG_ERROR,"[MTP3]%s %s : %s : OPC(0x%X%X%X%X)\n",
ftdm_log(FTDM_LOG_WARNING,"[MTP3]%s %s : %s : OPC(0x%X%X%X%X)\n",
buf,
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
@ -392,7 +404,7 @@ void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta)
break;
/**********************************************************************/
case (LSN_EVENT_INV_SLC_OTHER_END):
ftdm_log(FTDM_LOG_ERROR,"[MTP3]%s %s : %s : SLC(%d)\n",
ftdm_log(FTDM_LOG_WARNING,"[MTP3]%s %s : %s : SLC(%d)\n",
buf,
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
@ -400,7 +412,7 @@ void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta)
break;
/**********************************************************************/
default:
ftdm_log(FTDM_LOG_DEBUG,"[MTP3]%s %s(%d) : %s(%d)\n",
ftdm_log(FTDM_LOG_WARNING,"[MTP3]%s %s(%d) : %s(%d)\n",
buf,
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
sta->t.usta.alarm.event,
@ -412,7 +424,7 @@ void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta)
break;
/**************************************************************************/
case (STNSAP):
ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s : %s\n",
ftdm_log(FTDM_LOG_WARNING,"[MTP3][SAPID:%d] %s : %s\n",
sta->hdr.elmId.elmntInst1,
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause));
@ -463,7 +475,7 @@ void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta)
break;
/**********************************************************************/
default:
ftdm_log(FTDM_LOG_ERROR,"[MTP3][DPC:0x%X%X%X%X] %s : %s\n",
ftdm_log(FTDM_LOG_WARNING,"[MTP3][DPC:0x%X%X%X%X] %s : %s\n",
sta->t.usta.evntParm[0],
sta->t.usta.evntParm[1],
sta->t.usta.evntParm[2],
@ -733,7 +745,7 @@ void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
} /* switch (sta->t.usta.dgn.dgnVal[x].t.type) */
} /* for (x = 0; x < 5; x++) */
ftdm_log(FTDM_LOG_ERROR,"%s %s : %s\n",
ftdm_log(FTDM_LOG_WARNING,"%s %s : %s\n",
msg,
DECODE_LSI_EVENT(sta->t.usta.alarm.event),
DECODE_LSI_CAUSE(sta->t.usta.alarm.cause));
@ -759,7 +771,7 @@ void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta)
switch (sta->hdr.elmId.elmnt) {
/**************************************************************************/
case (LRY_USTA_ERR): /* ERROR */
ftdm_log(FTDM_LOG_ERROR,"[RELAY] Error: tx procId %d: err procId %d: channel %d: seq %s: reason %s\n",
ftdm_log(FTDM_LOG_WARNING,"[RELAY] Error: tx procId %d: err procId %d: channel %d: seq %s: reason %s\n",
sta->t.usta.s.ryErrUsta.sendPid,
sta->t.usta.s.ryErrUsta.errPid,
sta->t.usta.s.ryErrUsta.id,
@ -783,7 +795,7 @@ void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta)
break;
/**************************************************************************/
case (LRY_USTA_CNG): /* Congestion */
ftdm_log(FTDM_LOG_ERROR,"[RELAY] Congestion: tx procId %d: rem procId %d: channel %d: %s\n",
ftdm_log(FTDM_LOG_WARNING,"[RELAY] Congestion: tx procId %d: rem procId %d: channel %d: %s\n",
sta->t.usta.s.ryCongUsta.sendPid,
sta->t.usta.s.ryCongUsta.remPid,
sta->t.usta.s.ryCongUsta.id,
@ -791,7 +803,7 @@ void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta)
break;
/**************************************************************************/
case (LRY_USTA_UP): /* channel up */
ftdm_log(FTDM_LOG_ERROR,"[RELAY] Channel UP: tx procId %d: channel %d\n",
ftdm_log(FTDM_LOG_INFO,"[RELAY] Channel UP: tx procId %d: channel %d\n",
sta->t.usta.s.ryUpUsta.sendPid,
sta->t.usta.s.ryUpUsta.id);
@ -801,7 +813,7 @@ void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta)
break;
/**************************************************************************/
case (LRY_USTA_DN): /* channel down */
ftdm_log(FTDM_LOG_ERROR,"[RELAY] Channel DOWN: tx procId %d: channel %d\n",
ftdm_log(FTDM_LOG_WARNING,"[RELAY] Channel DOWN: tx procId %d: channel %d\n",
sta->t.usta.s.ryUpUsta.sendPid,
sta->t.usta.s.ryUpUsta.id);
@ -810,6 +822,11 @@ void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta)
break;
/**************************************************************************/
case (LRY_USTA_TCP_CONN_FAILED):
ftdm_log(FTDM_LOG_WARNING,"[RELAY] TCP connection failed \n" );
break;
/**************************************************************************/
default:
ftdm_log(FTDM_LOG_ERROR,"Unknown Relay Alram\n");
break;
@ -819,6 +836,311 @@ void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta)
return;
}
/******************************************************************************/
void handle_sng_m2ua_alarm(Pst *pst, MwMgmt *sta)
{
/* To print the general information */
ftdm_log(FTDM_LOG_INFO, "Recieved a status indication from M2UA layer \n\n");
ftdm_log(FTDM_LOG_INFO," Category = %d , event = %d , cause = %d\n",
sta->t.usta.alarm.category, sta->t.usta.alarm.event, sta->t.usta.alarm.cause);
/* To print the affected element value */
switch(sta->hdr.elmId.elmnt)
{
case STMWDLSAP:
{
ftdm_log(FTDM_LOG_INFO," STMWDLSAP: with lnkNmb (%d) \n\n",
sta->t.usta.s.lnkNmb);
break;
}
case STMWSCTSAP:
{
ftdm_log(FTDM_LOG_INFO," STMWSCTSAP: suId (%d) \n\n",
sta->t.usta.s.suId);
break;
}
case STMWPEER:
{
ftdm_log(FTDM_LOG_INFO," STMWPEER: peerId (%d) \n\n",
sta->t.usta.s.peerId);
break;
}
case STMWCLUSTER:
{
ftdm_log(FTDM_LOG_INFO," STMWCLUSTER: clusterId (%d) \n\n",
sta->t.usta.s.peerId);
break;
}
default:
{
ftdm_log(FTDM_LOG_ERROR, "[MW_USTA]: Invalid element \n\n");
break;
}
}
/* To print the event specific information */
switch(sta->t.usta.alarm.event)
{
case LMW_EVENT_TERM_OK:
{
ftdm_log(FTDM_LOG_INFO," M2UA : LMW_EVENT_TERM_OK: Association Terminated with PeerId[%d] \n",sta->t.usta.s.peerId);
break;
}
case LMW_EVENT_ENDPOPEN_OK:
{
ftdm_log(FTDM_LOG_INFO," M2UA : LMW_EVENT_ENDPOPEN_OK: \n");
break;
}
case LMW_EVENT_ESTABLISH_OK:
{
ftdm_log(FTDM_LOG_INFO," M2UA : LMW_EVENT_ESTABLISH_OK Event raised on peerId[%d]\n",sta->t.usta.s.peerId);
break;
}
case LMW_EVENT_ESTABLISH_FAIL:
{
ftdm_log(FTDM_LOG_INFO," M2UA : LMW_EVENT_ESTABLISH_FAIL Event raised on peerId[%d]\n",sta->t.usta.s.peerId);
break;
}
case LMW_EVENT_ASPM:
{
ftdm_log(FTDM_LOG_INFO," M2UA : LMW_EVENT_ASPM Event raised with peerId (%d), aspId (%d),"
" msgType (%d)\n\n",sta->t.usta.s.peerId,
sta->t.usta.t.aspm.msgType);
break;
}
case LMW_EVENT_CLUSTER:
{
ftdm_log(FTDM_LOG_INFO," M2UA : LMW_EVENT_CLUSTER Event raised on clusterId (%d), state (%d)\n\n",
sta->t.usta.s.clusterId, sta->t.usta.t.cluster.state);
break;
}
case LMW_EVENT_NOTIFY:
{
ftdm_log(FTDM_LOG_INFO," M2UA : LMW_EVENT_NOTIFY: peerId (%d), aspId (%d), ntfy status type (%d),"
" ntfy status id (%d)\n\n", sta->t.usta.s.peerId,
sta->t.usta.t.ntfy.aspId, sta->t.usta.t.ntfy.stType,
sta->t.usta.t.ntfy.stId);
break;
}
case LMW_EVENT_M2UA_PROTO_ERROR:
{
ftdm_log(FTDM_LOG_ERROR, " M2UA : LMW_EVENT_M2UA_PROTO_ERROR with errorCode (%d)\n\n",
sta->t.usta.t.error.errCode);
break;
}
default:
break;
}
} /* handle_sng_m2ua_alarm */
/******************************************************************************/
void handle_sng_nif_alarm(Pst *pst, NwMgmt *sta)
{
/* To print the general information */
ftdm_log(FTDM_LOG_INFO," Recieved a status indication from NIF layer\n");
ftdm_log(FTDM_LOG_INFO," Category = %d , event = %d , cause = %d\n", sta->t.usta.alarm.category,
sta->t.usta.alarm.event, sta->t.usta.alarm.cause);
switch(sta->hdr.elmId.elmnt)
{
case STNWDLSAP:
{
ftdm_log(FTDM_LOG_INFO," Recieved STNWDLSAP status indication for suId (%d) \n", sta->t.usta.suId);
switch(sta->t.usta.alarm.event)
{
case LCM_EVENT_LI_INV_EVT:
{
switch(sta->t.usta.alarm.cause)
{
case LCM_CAUSE_INV_SAP:
{
ftdm_log(FTDM_LOG_ERROR, " LCM_CAUSE_INV_SAP Alarm \n");
break;
}
case LCM_CAUSE_INV_STATE:
{
ftdm_log(FTDM_LOG_ERROR, " LCM_CAUSE_INV_STATE Alarm \n");
break;
}
default:
break;
}
break;
}
case LCM_EVENT_BND_OK:
{
ftdm_log(FTDM_LOG_INFO," NIF: LCM_EVENT_BND_OK Alarm \n");
break;
}
case LCM_EVENT_BND_FAIL:
{
ftdm_log(FTDM_LOG_INFO," NIF: LCM_EVENT_BND_FAIL Alarm \n");
break;
}
default:
break;
}
break;
}
default:
break;
}
} /* handle_sng_nif_alarm */
/******************************************************************************/
void handle_sng_tucl_alarm(Pst *pst, HiMngmt *sta)
{
/* To print the general information */
ftdm_log(FTDM_LOG_INFO, "Recieved a status indication from TUCL layer \n\n");
ftdm_log(FTDM_LOG_INFO, " Category = %d , event = %d , cause = %d\n",
sta->t.usta.alarm.category,
sta->t.usta.alarm.event, sta->t.usta.alarm.cause);
switch(sta->t.usta.alarm.event)
{
case LCM_EVENT_INV_EVT:
{
ftdm_log(FTDM_LOG_INFO," [HI_USTA]: LCM_EVENT_INV_EVT with type (%d)\n\n",
sta->t.usta.info.type);
break;
}
case LHI_EVENT_BNDREQ:
{
ftdm_log(FTDM_LOG_INFO," [HI_USTA]: LHI_EVENT_BNDREQ with type (%d) spId (%d)\n\n",
sta->t.usta.info.type, sta->t.usta.info.spId);
break;
}
case LHI_EVENT_SERVOPENREQ:
case LHI_EVENT_DATREQ:
case LHI_EVENT_UDATREQ:
case LHI_EVENT_CONREQ:
case LHI_EVENT_DISCREQ:
#if(defined(HI_TLS) && defined(HI_TCP_TLS))
case LHI_EVENT_TLS_ESTREQ:
#endif
{
ftdm_log(FTDM_LOG_INFO," [HI_USTA]: partype (%d) type(%d)\n\n",
sta->t.usta.info.inf.parType, sta->t.usta.info.type);
break;
}
case LCM_EVENT_DMEM_ALLOC_FAIL:
case LCM_EVENT_SMEM_ALLOC_FAIL:
{
ftdm_log(FTDM_LOG_ERROR," [HI_USTA]: MEM_ALLOC_FAIL with region(%d) pool (%d) type(%d)\n\n",
sta->t.usta.info.inf.mem.region, sta->t.usta.info.inf.mem.pool,
sta->t.usta.info.type);
break;
}
default:
break;
}
} /* handle_sng_tucl_alarm */
/******************************************************************************/
void handle_sng_sctp_alarm(Pst *pst, SbMgmt *sta)
{
ftdm_log(FTDM_LOG_INFO, "Recieved a status indication from SCTP layer \n\n");
ftdm_log(FTDM_LOG_INFO," Category = %d , event = %d , cause = %d "
" [SB_USTA]: sapId (%d) and swtch (%d)\n",
sta->t.usta.alarm.category,
sta->t.usta.alarm.event, sta->t.usta.alarm.cause,
sta->t.usta.sapId, sta->t.usta.swtch);
switch(sta->t.usta.alarm.category)
{
case LCM_CATEGORY_INTERFACE:
{
switch(sta->t.usta.alarm.cause)
{
case LCM_CAUSE_INV_SPID:
{
ftdm_log(FTDM_LOG_ERROR, "SCTP : LCM_CAUSE_INV_SPID Alarm \n");
break;
}
case LCM_CAUSE_SWVER_NAVAIL:
{
ftdm_log(FTDM_LOG_ERROR, "SCTP : LCM_CAUSE_SWVER_NAVAIL Alarm\n");
break;
}
case LCM_CAUSE_INV_PAR_VAL:
{
ftdm_log(FTDM_LOG_ERROR, "SCTP : LCM_CAUSE_INV_PAR_VAL Alarm\n");
break;
}
case LCM_CAUSE_INV_SUID:
{
ftdm_log(FTDM_LOG_ERROR, "SCTP : LCM_CAUSE_INV_SUID Alarm\n");
break;
}
case LCM_CAUSE_INV_SAP:
{
ftdm_log(FTDM_LOG_ERROR, "SCTP : LCM_CAUSE_INV_SAP Alarm\n");
break;
}
default:
break;
}
break;
}
case LCM_CATEGORY_RESOURCE:
{
switch(sta->t.usta.alarm.cause)
{
case LCM_CAUSE_MEM_ALLOC_FAIL:
{
ftdm_log(FTDM_LOG_ERROR, "SCTP : LCM_CAUSE_MEM_ALLOC_FAIL Alarm \n");
break;
}
case LSB_CAUSE_NUM_ADDR_EXCEED:
{
ftdm_log(FTDM_LOG_ERROR, "SCTP : LSB_CAUSE_NUM_ADDR_EXCEED Alarm\n");
break;
}
default:
break;
}
break;
}
case LCM_CATEGORY_PROTOCOL:
{
switch(sta->t.usta.alarm.cause)
{
case LSB_CAUSE_PATH_FAILURE:
{
ftdm_log(FTDM_LOG_ERROR, "SCTP : LSB_CAUSE_PATH_FAILURE Alarm \n");
break;
}
case LSB_CAUSE_PATH_ACTIVE:
{
ftdm_log(FTDM_LOG_ERROR, "SCTP : LSB_CAUSE_PATH_ACTIVE Alarm \n");
break;
}
case LSB_CAUSE_UNRSLVD_ADDR:
{
ftdm_log(FTDM_LOG_ERROR, "SCTP : LSB_CAUSE_UNRSLVD_ADDR Alarm \n");
break;
}
default:
break;
}
break;
}
default:
break;
}
} /* handle_sng_sctp_alarm */
/******************************************************************************/
/******************************************************************************/
/* For Emacs:
* Local Variables:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,136 @@
/*
* Copyright (c) 2012, Kapil Gupta <kgupta@sangoma.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* 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:
*
*/
/******************************************************************************/
#ifndef __FTMOD_SNG_SS7_M2UA_H__
#define __FTMOD_SNG_SS7_M2UA_H__
/******************************************************************************/
#include "private/ftdm_core.h"
#define MAX_NAME_LEN 25
typedef struct sng_nif_cfg{
char name[MAX_NAME_LEN];
uint32_t flags;
uint32_t id;
uint32_t m2uaLnkNmb;
uint32_t mtp2LnkNmb;
}sng_nif_cfg_t;
typedef enum{
SNG_M2UA_NODE_TYPE_SGP = 1, /* type SG */
SNG_M2UA_NODE_TYPE_ASP = 2, /* type ASP */
}sng_m2ua_node_types_e;
typedef struct sng_m2ua_cfg{
char name[MAX_NAME_LEN];
uint32_t flags;
uint32_t id; /* ID */
uint32_t iid; /* ID */
uint8_t nodeType; /*Node Type SG/ASP */
uint8_t end_point_opened; /* flag to check is end-point already opened */
uint16_t clusterId; /* idx to m2ua_cluster profile */
}sng_m2ua_cfg_t;
typedef struct sng_m2ua_peer_cfg{
char name[MAX_NAME_LEN];
uint32_t flags;
uint32_t id; /* ID */
uint8_t aspIdFlag; /* Flag used to indicate whether include the ASP ID in the ASP UP message */
uint16_t selfAspId; /* Self ASP ID. ASP identifier for this ASP node if the aspIdFlag is TRUE. */
uint32_t numDestAddr; /* Number of destination address defined */
uint16_t sctpId; /* idx to sctp profile */
uint16_t port;
uint32_t destAddrList[SCT_MAX_NET_ADDRS+1]; /* Destination adddress list */
uint16_t locOutStrms; /*Number of outgoing streams supported by this association*/
int init_sctp_assoc; /* flag to tell if we need to initiate SCTP association */
}sng_m2ua_peer_cfg_t;
typedef enum{
SNG_M2UA_LOAD_SHARE_ALGO_RR = 0x1, /* Round Robin Mode*/
SNG_M2UA_LOAD_SHARE_ALGO_LS = 0x2, /* Link Specified */
SNG_M2UA_LOAD_SHARE_ALGO_CS = 0x3, /* Customer Specified */
}sng_m2ua_load_share_algo_types_e;
/* Possible values of Traffic mode */
typedef enum{
SNG_M2UA_TRF_MODE_OVERRIDE = 0x1, /* Override Mode */
SNG_M2UA_TRF_MODE_LOADSHARE = 0x2, /* Loadshare Mode */
SNG_M2UA_TRF_MODE_BROADCAST = 0x3, /* Broadcast Mode */
SNG_M2UA_TRF_MODE_ANY = 0x0, /* ANY Mode */
}sng_m2ua_traffic_mode_types_e;
typedef struct sng_m2ua_cluster_cfg{
char name[MAX_NAME_LEN];
uint32_t flags;
uint32_t id; /* ID */
uint32_t sct_sap_id; /* Internal - sct_sap_id */
uint8_t trfMode; /* Traffic mode. This parameter defines the mode in which this m2ua cluster is supposed to work */
uint8_t loadShareAlgo; /* This parameter defines the M2UA load share algorithm which is used to distribute the traffic */
uint16_t numOfPeers; /* idx to m2ua_peer profile */
uint16_t peerIdLst[MW_MAX_NUM_OF_PEER]; /* idx to m2ua_peer profile */
}sng_m2ua_cluster_cfg_t;
typedef struct sng_m2ua_gbl_cfg{
sng_nif_cfg_t nif[MW_MAX_NUM_OF_INTF+1];
sng_m2ua_cfg_t m2ua[MW_MAX_NUM_OF_INTF+1];
sng_m2ua_peer_cfg_t m2ua_peer[MW_MAX_NUM_OF_PEER+1];
sng_m2ua_cluster_cfg_t m2ua_clus[MW_MAX_NUM_OF_CLUSTER+1];
}sng_m2ua_gbl_cfg_t;
/* m2ua xml parsing APIs */
int ftmod_ss7_parse_nif_interfaces(ftdm_conf_node_t *nif_interfaces);
int ftmod_ss7_parse_m2ua_interfaces(ftdm_conf_node_t *m2ua_interfaces);
int ftmod_ss7_parse_m2ua_peer_interfaces(ftdm_conf_node_t *m2ua_peer_interfaces);
int ftmod_ss7_parse_m2ua_clust_interfaces(ftdm_conf_node_t *m2ua_clust_interfaces);
int ftmod_ss7_parse_sctp_links(ftdm_conf_node_t *node);
uint32_t iptoul(const char *ip);
int ftmod_ss7_m2ua_start(void);
void ftmod_ss7_m2ua_free(void);
ftdm_status_t ftmod_ss7_m2ua_cfg(void);
ftdm_status_t ftmod_ss7_m2ua_init(void);
int ftmod_sctp_ssta_req(int elemt, int id, SbMgmt* cfm);
int ftmod_m2ua_ssta_req(int elemt, int id, MwMgmt* cfm);
int ftmod_nif_ssta_req(int elemt, int id, NwMgmt* cfm);
void ftmod_ss7_enable_m2ua_sg_logging(void);
void ftmod_ss7_disable_m2ua_sg_logging(void);
#endif /*__FTMOD_SNG_SS7_M2UA_H__*/

View File

@ -0,0 +1,690 @@
/*
* Copyright (c) 2012, Kapil Gupta <kgupta@sangoma.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* 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:
*
*
*/
/* INCLUDE ********************************************************************/
#include "ftmod_sangoma_ss7_main.h"
/******************************************************************************/
/* DEFINES ********************************************************************/
/******************************************************************************/
static int ftmod_ss7_parse_nif_interface(ftdm_conf_node_t *nif_interface);
static int ftmod_ss7_parse_m2ua_interface(ftdm_conf_node_t *m2ua_interface);
static int ftmod_ss7_parse_m2ua_peer_interface(ftdm_conf_node_t *m2ua_peer_interface);
static int ftmod_ss7_parse_m2ua_clust_interface(ftdm_conf_node_t *m2ua_clust_interface);
static int ftmod_ss7_fill_in_nif_interface(sng_nif_cfg_t *nif_iface);
static int ftmod_ss7_fill_in_m2ua_interface(sng_m2ua_cfg_t *m2ua_iface);
static int ftmod_ss7_fill_in_m2ua_peer_interface(sng_m2ua_peer_cfg_t *m2ua_peer_face);
static int ftmod_ss7_fill_in_m2ua_clust_interface(sng_m2ua_cluster_cfg_t *m2ua_cluster_face);
static int ftmod_ss7_parse_sctp_link(ftdm_conf_node_t *node);
/******************************************************************************/
int ftmod_ss7_parse_nif_interfaces(ftdm_conf_node_t *nif_interfaces)
{
ftdm_conf_node_t *nif_interface = NULL;
/* confirm that we are looking at sng_nif_interfaces */
if (strcasecmp(nif_interfaces->name, "sng_nif_interfaces")) {
SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"sng_nif_interfaces\"!\n",nif_interfaces->name);
return FTDM_FAIL;
} else {
SS7_DEBUG("Parsing \"nif_interfaces\"...\n");
}
/* extract the isup_interfaces */
nif_interface = nif_interfaces->child;
while (nif_interface != NULL) {
/* parse the found mtp_route */
if (ftmod_ss7_parse_nif_interface(nif_interface)) {
SS7_ERROR("Failed to parse \"nif_interface\"\n");
return FTDM_FAIL;
}
/* go to the next nif_interface */
nif_interface = nif_interface->next;
}
return FTDM_SUCCESS;
}
/******************************************************************************/
static int ftmod_ss7_parse_nif_interface(ftdm_conf_node_t *nif_interface)
{
sng_nif_cfg_t sng_nif;
ftdm_conf_parameter_t *parm = nif_interface->parameters;
int num_parms = nif_interface->n_parameters;
int i;
/* initalize the nif intf and isap structure */
memset(&sng_nif, 0x0, sizeof(sng_nif));
if(!nif_interface){
SS7_ERROR("ftmod_ss7_parse_nif_interface: Null XML Node pointer \n");
return FTDM_FAIL;
}
/* confirm that we are looking at an nif_interface */
if (strcasecmp(nif_interface->name, "sng_nif_interface")) {
SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"nif_interface\"!\n",nif_interface->name);
return FTDM_FAIL;
} else {
SS7_DEBUG("Parsing \"nif_interface\"...\n");
}
for (i = 0; i < num_parms; i++) {
/**************************************************************************/
/* try to match the parameter to what we expect */
if (!strcasecmp(parm->var, "name")) {
/**********************************************************************/
strcpy((char *)sng_nif.name, parm->val);
SS7_DEBUG("Found an nif_interface named = %s\n", sng_nif.name);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "id")) {
/**********************************************************************/
sng_nif.id = atoi(parm->val);
SS7_DEBUG("Found an nif id = %d\n", sng_nif.id);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "m2ua-interface-id")) {
/**********************************************************************/
sng_nif.m2uaLnkNmb = atoi(parm->val);
SS7_DEBUG("Found an nif m2ua-interface-id = %d\n", sng_nif.m2uaLnkNmb);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "mtp2-interface-id")) {
/**********************************************************************/
sng_nif.mtp2LnkNmb=atoi(parm->val);
SS7_DEBUG("Found an nif mtp2-interface-id = %d\n", sng_nif.mtp2LnkNmb);
/**********************************************************************/
} else {
/**********************************************************************/
SS7_ERROR("Found an invalid parameter %s!\n", parm->var);
return FTDM_FAIL;
/**********************************************************************/
}
/* move to the next parameter */
parm = parm + 1;
/**************************************************************************/
} /* for (i = 0; i < num_parms; i++) */
/* fill in the nif interface */
ftmod_ss7_fill_in_nif_interface(&sng_nif);
return FTDM_SUCCESS;
}
/******************************************************************************/
static int ftmod_ss7_fill_in_nif_interface(sng_nif_cfg_t *nif_iface)
{
int i = nif_iface->id;
strncpy((char *)g_ftdm_sngss7_data.cfg.g_m2ua_cfg.nif[i].name, (char *)nif_iface->name, MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.nif[i].id = nif_iface->id;
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.nif[i].m2uaLnkNmb = nif_iface->m2uaLnkNmb;
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.nif[i].mtp2LnkNmb = nif_iface->mtp2LnkNmb;
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_NIF_PRESENT);
return 0;
}
/******************************************************************************/
int ftmod_ss7_parse_m2ua_interfaces(ftdm_conf_node_t *m2ua_interfaces)
{
ftdm_conf_node_t *m2ua_interface = NULL;
/* confirm that we are looking at sng_m2ua_interfaces */
if (strcasecmp(m2ua_interfaces->name, "sng_m2ua_interfaces")) {
SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"m2ua_nif_interfaces\"!\n",m2ua_interfaces->name);
return FTDM_FAIL;
} else {
SS7_DEBUG("Parsing \"m2ua_interfaces\"...\n");
}
/* extract the isup_interfaces */
m2ua_interface = m2ua_interfaces->child;
while (m2ua_interface != NULL) {
/* parse the found mtp_route */
if (ftmod_ss7_parse_m2ua_interface(m2ua_interface)) {
SS7_ERROR("Failed to parse \"m2ua_interface\"\n");
return FTDM_FAIL;
}
/* go to the next m2ua_interface */
m2ua_interface = m2ua_interface->next;
}
return FTDM_SUCCESS;
}
/******************************************************************************/
static int ftmod_ss7_parse_m2ua_interface(ftdm_conf_node_t *m2ua_interface)
{
sng_m2ua_cfg_t sng_m2ua;
ftdm_conf_parameter_t *parm = m2ua_interface->parameters;
int num_parms = m2ua_interface->n_parameters;
int i;
/* initalize the m2ua intf */
memset(&sng_m2ua, 0x0, sizeof(sng_m2ua));
if(!m2ua_interface){
SS7_ERROR("ftmod_ss7_parse_m2ua_interface: Null XML Node pointer \n");
return FTDM_FAIL;
}
/* confirm that we are looking at an nif_interface */
if (strcasecmp(m2ua_interface->name, "sng_m2ua_interface")) {
SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"m2ua_interface\"!\n",m2ua_interface->name);
return FTDM_FAIL;
} else {
SS7_DEBUG("Parsing \"m2ua_interface\"...\n");
}
for (i = 0; i < num_parms; i++) {
/**************************************************************************/
/* try to match the parameter to what we expect */
if (!strcasecmp(parm->var, "name")) {
/**********************************************************************/
strcpy((char *)sng_m2ua.name, parm->val);
SS7_DEBUG("Found an m2ua_interface named = %s\n", sng_m2ua.name);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "id")) {
/**********************************************************************/
sng_m2ua.id = atoi(parm->val);
SS7_DEBUG("Found an m2ua id = %d\n", sng_m2ua.id);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "m2ua-cluster-interface-id")) {
/**********************************************************************/
sng_m2ua.clusterId=atoi(parm->val);
SS7_DEBUG("Found an m2ua cluster_id = %d\n", sng_m2ua.clusterId);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "interface-identifier")) {
/**********************************************************************/
sng_m2ua.iid=atoi(parm->val);
SS7_DEBUG("Found an m2ua interface-identifier = %d\n", sng_m2ua.iid);
/**********************************************************************/
} else {
/**********************************************************************/
SS7_ERROR("Found an invalid parameter %s!\n", parm->var);
return FTDM_FAIL;
/**********************************************************************/
}
/* move to the next parameter */
parm = parm + 1;
/**************************************************************************/
} /* for (i = 0; i < num_parms; i++) */
sng_m2ua.nodeType = SNG_M2UA_NODE_TYPE_SGP;
/* fill in the nif interface */
ftmod_ss7_fill_in_m2ua_interface(&sng_m2ua);
return FTDM_SUCCESS;
}
/******************************************************************************/
static int ftmod_ss7_fill_in_m2ua_interface(sng_m2ua_cfg_t *m2ua_iface)
{
int i = m2ua_iface->id;
strncpy((char *)g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[i].name, (char *)m2ua_iface->name, MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[i].id = m2ua_iface->id;
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[i].nodeType = m2ua_iface->nodeType;
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[i].clusterId = m2ua_iface->clusterId;
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua[i].iid = m2ua_iface->iid;
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_M2UA_PRESENT);
return 0;
}
/******************************************************************************/
int ftmod_ss7_parse_m2ua_peer_interfaces(ftdm_conf_node_t *m2ua_peer_interfaces)
{
ftdm_conf_node_t *m2ua_peer_interface = NULL;
/* confirm that we are looking at m2ua_peer_interfaces */
if (strcasecmp(m2ua_peer_interfaces->name, "sng_m2ua_peer_interfaces")) {
SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"m2ua_peer_interfaces\"!\n",m2ua_peer_interfaces->name);
return FTDM_FAIL;
} else {
SS7_DEBUG("Parsing \"m2ua_peer_interfaces\"...\n");
}
/* extract the m2ua_peer_interfaces */
m2ua_peer_interface = m2ua_peer_interfaces->child;
while (m2ua_peer_interface != NULL) {
/* parse the found mtp_route */
if (ftmod_ss7_parse_m2ua_peer_interface(m2ua_peer_interface)) {
SS7_ERROR("Failed to parse \"m2ua_peer_interface\"\n");
return FTDM_FAIL;
}
/* go to the next m2ua_peer_interface */
m2ua_peer_interface = m2ua_peer_interface->next;
}
return FTDM_SUCCESS;
}
/******************************************************************************/
static int ftmod_ss7_parse_m2ua_peer_interface(ftdm_conf_node_t *m2ua_peer_interface)
{
sng_m2ua_peer_cfg_t sng_m2ua_peer;
ftdm_conf_parameter_t *parm = m2ua_peer_interface->parameters;
int num_parms = m2ua_peer_interface->n_parameters;
int i;
/* initalize the m2ua intf */
memset(&sng_m2ua_peer, 0x0, sizeof(sng_m2ua_peer));
if(!m2ua_peer_interface){
SS7_ERROR("ftmod_ss7_parse_m2ua_peer_interface: Null XML Node pointer \n");
return FTDM_FAIL;
}
/* confirm that we are looking at an m2ua_peer_interface */
if (strcasecmp(m2ua_peer_interface->name, "sng_m2ua_peer_interface")) {
SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"m2ua_peer_interface\"!\n",m2ua_peer_interface->name);
return FTDM_FAIL;
} else {
SS7_DEBUG("Parsing \"m2ua_peer_interface\"...\n");
}
for (i = 0; i < num_parms; i++) {
/**************************************************************************/
/* try to match the parameter to what we expect */
if (!strcasecmp(parm->var, "name")) {
/**********************************************************************/
strcpy((char *)sng_m2ua_peer.name, parm->val);
SS7_DEBUG("Found an sng_m2ua_peer named = %s\n", sng_m2ua_peer.name);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "id")) {
/**********************************************************************/
sng_m2ua_peer.id = atoi(parm->val);
SS7_DEBUG("Found an sng_m2ua_peer id = %d\n", sng_m2ua_peer.id);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "include-asp-identifier")) {
/**********************************************************************/
if(!strcasecmp(parm->val, "TRUE")){
sng_m2ua_peer.aspIdFlag = 0x01;
} else if(!strcasecmp(parm->val, "FALSE")){
sng_m2ua_peer.aspIdFlag = 0x00;
} else {
SS7_ERROR("Found an invalid aspIdFlag Parameter Value[%s]\n", parm->val);
return FTDM_FAIL;
}
SS7_DEBUG("Found an sng_m2ua_peer aspIdFlag = %d\n", sng_m2ua_peer.aspIdFlag);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "asp-identifier")) {
/**********************************************************************/
sng_m2ua_peer.selfAspId=atoi(parm->val);
SS7_DEBUG("Found an sng_m2ua_peer self_asp_id = %d\n", sng_m2ua_peer.selfAspId);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "sctp-interface-id")) {
/**********************************************************************/
sng_m2ua_peer.sctpId = atoi(parm->val);
SS7_DEBUG("Found an sng_m2ua_peer sctp_id = %d\n", sng_m2ua_peer.sctpId);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "destination-port")) {
/**********************************************************************/
sng_m2ua_peer.port = atoi(parm->val);
SS7_DEBUG("Found an sng_m2ua_peer port = %d\n", sng_m2ua_peer.port);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "address")) {
/**********************************************************************/
if (sng_m2ua_peer.numDestAddr < SCT_MAX_NET_ADDRS) {
sng_m2ua_peer.destAddrList[sng_m2ua_peer.numDestAddr] = iptoul (parm->val);
sng_m2ua_peer.numDestAddr++;
SS7_DEBUG("sng_m2ua_peer - Parsing with dest IP Address = %s \n", parm->val);
} else {
SS7_ERROR("sng_m2ua_peer - too many dest address configured. dropping %s \n", parm->val);
}
/**********************************************************************/
} else if (!strcasecmp(parm->var, "number-of-outgoing-streams")) {
/**********************************************************************/
sng_m2ua_peer.locOutStrms=atoi(parm->val);
SS7_DEBUG("Found an sng_m2ua_peer number-of-outgoing-streams = %d\n", sng_m2ua_peer.locOutStrms);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "init-sctp-association")) {
/**********************************************************************/
if(!strcasecmp(parm->val, "TRUE")){
sng_m2ua_peer.init_sctp_assoc = 0x01;
} else if(!strcasecmp(parm->val, "FALSE")){
sng_m2ua_peer.init_sctp_assoc = 0x00;
} else {
SS7_ERROR("Found an invalid init_sctp_assoc Parameter Value[%s]\n", parm->val);
return FTDM_FAIL;
}
SS7_DEBUG("Found an sng_m2ua_peer init_sctp_assoc = %d\n", sng_m2ua_peer.init_sctp_assoc);
/**********************************************************************/
} else {
/**********************************************************************/
SS7_ERROR("Found an invalid parameter %s!\n", parm->var);
return FTDM_FAIL;
/**********************************************************************/
}
/* move to the next parameter */
parm = parm + 1;
/**************************************************************************/
} /* for (i = 0; i < num_parms; i++) */
/* fill in the sng_m2ua_peer interface */
ftmod_ss7_fill_in_m2ua_peer_interface(&sng_m2ua_peer);
return FTDM_SUCCESS;
}
/******************************************************************************/
static int ftmod_ss7_fill_in_m2ua_peer_interface(sng_m2ua_peer_cfg_t *m2ua_peer_iface)
{
int k = 0x00;
int i = m2ua_peer_iface->id;
strncpy((char *)g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].name, (char *)m2ua_peer_iface->name, MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].id = m2ua_peer_iface->id;
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].aspIdFlag = m2ua_peer_iface->aspIdFlag;
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].selfAspId = m2ua_peer_iface->selfAspId;
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].locOutStrms = m2ua_peer_iface->locOutStrms;
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].numDestAddr = m2ua_peer_iface->numDestAddr;
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].sctpId = m2ua_peer_iface->sctpId;
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].port = m2ua_peer_iface->port;
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].init_sctp_assoc = m2ua_peer_iface->init_sctp_assoc;
for (k=0; k<m2ua_peer_iface->numDestAddr; k++) {
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_peer[i].destAddrList[k] = m2ua_peer_iface->destAddrList[k];
}
return 0;
}
/******************************************************************************/
int ftmod_ss7_parse_m2ua_clust_interfaces(ftdm_conf_node_t *m2ua_cluster_interfaces)
{
ftdm_conf_node_t *m2ua_cluster_interface = NULL;
/* confirm that we are looking at m2ua_cluster_interfaces */
if (strcasecmp(m2ua_cluster_interfaces->name, "sng_m2ua_cluster_interfaces")) {
SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"m2ua_cluster_interfaces\"!\n",m2ua_cluster_interfaces->name);
return FTDM_FAIL;
} else {
SS7_DEBUG("Parsing \"m2ua_cluster_interfaces\"...\n");
}
/* extract the m2ua_cluster_interfaces */
m2ua_cluster_interface = m2ua_cluster_interfaces->child;
while (m2ua_cluster_interface != NULL) {
/* parse the found m2ua_cluster_interface */
if (ftmod_ss7_parse_m2ua_clust_interface(m2ua_cluster_interface)) {
SS7_ERROR("Failed to parse \"m2ua_cluster_interface\"\n");
return FTDM_FAIL;
}
/* go to the next m2ua_cluster_interface */
m2ua_cluster_interface = m2ua_cluster_interface->next;
}
return FTDM_SUCCESS;
}
/******************************************************************************/
static int ftmod_ss7_parse_m2ua_clust_interface(ftdm_conf_node_t *m2ua_cluster_interface)
{
sng_m2ua_cluster_cfg_t sng_m2ua_cluster;
ftdm_conf_parameter_t *parm = m2ua_cluster_interface->parameters;
int num_parms = m2ua_cluster_interface->n_parameters;
int i;
/* initalize the m2ua_cluster_interface */
memset(&sng_m2ua_cluster, 0x0, sizeof(sng_m2ua_cluster));
if (!m2ua_cluster_interface){
SS7_ERROR("ftmod_ss7_parse_m2ua_clust_interface - NULL XML Node pointer \n");
return FTDM_FAIL;
}
/* confirm that we are looking at an m2ua_cluster_interface */
if (strcasecmp(m2ua_cluster_interface->name, "sng_m2ua_cluster_interface")) {
SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"m2ua_cluster_interface\"!\n",m2ua_cluster_interface->name);
return FTDM_FAIL;
} else {
SS7_DEBUG("Parsing \"m2ua_cluster_interface\"...\n");
}
for (i = 0; i < num_parms; i++) {
/**************************************************************************/
/* try to match the parameter to what we expect */
if (!strcasecmp(parm->var, "name")) {
/**********************************************************************/
strcpy((char *)sng_m2ua_cluster.name, parm->val);
SS7_DEBUG("Found an sng_m2ua_cluster named = %s\n", sng_m2ua_cluster.name);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "id")) {
/**********************************************************************/
sng_m2ua_cluster.id = atoi(parm->val);
SS7_DEBUG("Found an sng_m2ua_cluster id = %d\n", sng_m2ua_cluster.id);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "traffic-mode")) {
/**********************************************************************/
if(!strcasecmp(parm->val, "loadshare")){
sng_m2ua_cluster.trfMode = SNG_M2UA_TRF_MODE_LOADSHARE;
} else if(!strcasecmp(parm->val, "override")){
sng_m2ua_cluster.trfMode = SNG_M2UA_TRF_MODE_OVERRIDE;
} else if(!strcasecmp(parm->val, "broadcast")){
sng_m2ua_cluster.trfMode = SNG_M2UA_TRF_MODE_BROADCAST;
} else {
SS7_ERROR("Found an invalid trfMode Parameter Value[%s]..adding default one[ANY]\n", parm->val);
sng_m2ua_cluster.trfMode = SNG_M2UA_TRF_MODE_ANY;
}
SS7_DEBUG("Found an sng_m2ua_cluster.trfMode = %d\n", sng_m2ua_cluster.trfMode);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "load-share-algorithm")) {
/**********************************************************************/
if(!strcasecmp(parm->val, "roundrobin")){
sng_m2ua_cluster.loadShareAlgo = SNG_M2UA_LOAD_SHARE_ALGO_RR;
} else if(!strcasecmp(parm->val, "linkspecified")){
sng_m2ua_cluster.loadShareAlgo = SNG_M2UA_LOAD_SHARE_ALGO_LS;
} else if(!strcasecmp(parm->val, "customerspecified")){
sng_m2ua_cluster.loadShareAlgo = SNG_M2UA_LOAD_SHARE_ALGO_CS;
} else {
SS7_ERROR("Found an invalid loadShareAlgo Parameter Value[%s]\n", parm->val);
return FTDM_FAIL;
}
SS7_DEBUG("Found an sng_m2ua_cluster.loadShareAlgo = %d\n", sng_m2ua_cluster.loadShareAlgo);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "m2ua-peer-interface-id")) {
/**********************************************************************/
if(sng_m2ua_cluster.numOfPeers < MW_MAX_NUM_OF_PEER) {
sng_m2ua_cluster.peerIdLst[sng_m2ua_cluster.numOfPeers] = atoi(parm->val);
SS7_DEBUG("Found an sng_m2ua_cluster peerId[%d], Total numOfPeers[%d] \n",
sng_m2ua_cluster.peerIdLst[sng_m2ua_cluster.numOfPeers],
sng_m2ua_cluster.numOfPeers+1);
sng_m2ua_cluster.numOfPeers++;
}else{
SS7_ERROR("Peer List excedding max[%d] limit \n", MW_MAX_NUM_OF_PEER);
return FTDM_FAIL;
}
/**********************************************************************/
} else {
/**********************************************************************/
SS7_ERROR("Found an invalid parameter %s!\n", parm->var);
return FTDM_FAIL;
/**********************************************************************/
}
/* move to the next parameter */
parm = parm + 1;
/**************************************************************************/
} /* for (i = 0; i < num_parms; i++) */
/* fill in the sng_m2ua_peer interface */
ftmod_ss7_fill_in_m2ua_clust_interface(&sng_m2ua_cluster);
return FTDM_SUCCESS;
}
/******************************************************************************/
static int ftmod_ss7_fill_in_m2ua_clust_interface(sng_m2ua_cluster_cfg_t *m2ua_cluster_iface)
{
int k = 0x00;
int i = m2ua_cluster_iface->id;
strncpy((char *)g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[i].name, (char *)m2ua_cluster_iface->name, MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[i].id = m2ua_cluster_iface->id;
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[i].trfMode = m2ua_cluster_iface->trfMode;
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[i].loadShareAlgo = m2ua_cluster_iface->loadShareAlgo;
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[i].numOfPeers = m2ua_cluster_iface->numOfPeers;
for(k=0;k<m2ua_cluster_iface->numOfPeers;k++){
g_ftdm_sngss7_data.cfg.g_m2ua_cfg.m2ua_clus[i].peerIdLst[k] = m2ua_cluster_iface->peerIdLst[k];
}
return 0;
}
/******************************************************************************/
int ftmod_ss7_parse_sctp_links(ftdm_conf_node_t *node)
{
ftdm_conf_node_t *node_sctp_link = NULL;
if (!node)
return FTDM_FAIL;
if (strcasecmp(node->name, "sng_sctp_interfaces")) {
SS7_ERROR("SCTP - We're looking at <%s>...but we're supposed to be looking at <sng_sctp_interfaces>!\n", node->name);
return FTDM_FAIL;
} else {
SS7_DEBUG("SCTP - Parsing <sng_sctp_interface> configurations\n");
}
for (node_sctp_link = node->child; node_sctp_link != NULL; node_sctp_link = node_sctp_link->next) {
if (ftmod_ss7_parse_sctp_link(node_sctp_link) != FTDM_SUCCESS) {
SS7_ERROR("SCTP - Failed to parse <node_sctp_link>. \n");
return FTDM_FAIL;
}
}
return FTDM_SUCCESS;
}
/******************************************************************************/
static int ftmod_ss7_parse_sctp_link(ftdm_conf_node_t *node)
{
ftdm_conf_parameter_t *param = NULL;
int num_params = 0;
int i=0;
if (!node){
SS7_ERROR("SCTP - NULL XML Node pointer \n");
return FTDM_FAIL;
}
param = node->parameters;
num_params = node->n_parameters;
sng_sctp_link_t t_link;
memset (&t_link, 0, sizeof(sng_sctp_link_t));
if (strcasecmp(node->name, "sng_sctp_interface")) {
SS7_ERROR("SCTP - We're looking at <%s>...but we're supposed to be looking at <sng_sctp_interface>!\n", node->name);
return FTDM_FAIL;
} else {
SS7_DEBUG("SCTP - Parsing <sng_sctp_interface> configurations\n");
}
for (i=0; i<num_params; i++, param++) {
if (!strcasecmp(param->var, "name")) {
int n_strlen = strlen(param->val);
strncpy((char*)t_link.name, param->val, (n_strlen>MAX_NAME_LEN)?MAX_NAME_LEN:n_strlen);
SS7_DEBUG("SCTP - Parsing <sng_sctp_interface> with name = %s\n", param->val);
}
else if (!strcasecmp(param->var, "id")) {
t_link.id = atoi(param->val);
SS7_DEBUG("SCTP - Parsing <sng_sctp_interface> with id = %s\n", param->val);
}
else if (!strcasecmp(param->var, "address")) {
if (t_link.numSrcAddr < SCT_MAX_NET_ADDRS) {
t_link.srcAddrList[t_link.numSrcAddr+1] = iptoul (param->val);
t_link.numSrcAddr++;
SS7_DEBUG("SCTP - Parsing <sng_sctp_interface> with source IP Address = %s\n", param->val);
} else {
SS7_ERROR("SCTP - too many source address configured. dropping %s \n", param->val);
}
} else if (!strcasecmp(param->var, "source-port")) {
t_link.port = atoi(param->val);
SS7_DEBUG("SCTP - Parsing <sng_sctp_interface> with port = %s\n", param->val);
}
else {
SS7_ERROR("SCTP - Found an unknown parameter <%s>. Skipping it.\n", param->var);
}
}
g_ftdm_sngss7_data.cfg.sctpCfg.linkCfg[t_link.id].id = t_link.id;
g_ftdm_sngss7_data.cfg.sctpCfg.linkCfg[t_link.id].port = t_link.port;
strncpy((char*)g_ftdm_sngss7_data.cfg.sctpCfg.linkCfg[t_link.id].name, t_link.name, strlen(t_link.name) );
g_ftdm_sngss7_data.cfg.sctpCfg.linkCfg[t_link.id].numSrcAddr = t_link.numSrcAddr;
for (i=1; i<=t_link.numSrcAddr; i++) {
g_ftdm_sngss7_data.cfg.sctpCfg.linkCfg[t_link.id].srcAddrList[i] = t_link.srcAddrList[i];
}
sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SCTP_PRESENT);
return FTDM_SUCCESS;
}
/******************************************************************************/

View File

@ -29,6 +29,12 @@
* 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:
*
* James Zhang <jzhang@sangoma.com>
*
*/
/******************************************************************************/
#ifndef __FTMOD_SNG_SS7_H__
@ -46,17 +52,20 @@
#include "private/ftdm_core.h"
#include "sng_ss7/sng_ss7.h"
#include "ftmod_sangoma_ss7_m2ua.h"
/******************************************************************************/
/* DEFINES ********************************************************************/
#define MAX_NAME_LEN 25
#define MAX_PATH 4096
#define MAX_CIC_LENGTH 5
#define MAX_CIC_MAP_LENGTH 1000
#define MAX_SCTP_LINK 100
#define SNGSS7_EVENT_QUEUE_SIZE 100
#define SNGSS7_PEER_CHANS_QUEUE_SIZE 100
#define SNGSS7_CHAN_EVENT_QUEUE_SIZE 100
#define MAX_SIZEOF_SUBADDR_IE 24 /* as per Q931 4.5.9 */
@ -64,6 +73,14 @@
(switchtype == LSI_SW_ANS92) || \
(switchtype == LSI_SW_ANS95)
#define sngss7_flush_queue(queue) \
do { \
void *__queue_data = NULL; \
while ((__queue_data = ftdm_queue_dequeue(queue))) { \
ftdm_safe_free(__queue_data); \
} \
} while (0)
typedef struct ftdm2trillium {
uint8_t ftdm_val;
uint8_t trillium_val;
@ -82,8 +99,12 @@ typedef enum {
SNGSS7_STA_IND_EVENT,
SNGSS7_SUSP_IND_EVENT,
SNGSS7_RESM_IND_EVENT,
SNGSS7_SSP_STA_CFM_EVENT
SNGSS7_SSP_STA_CFM_EVENT,
SNGSS7_INVALID_EVENT,
} sng_event_type_t;
#define SNG_EVENT_TYPE_STRINGS "CON_IND", "CON_CFM", "CON_STA", "REL_IND", "REL_CFM", "DAT_IND", "FAC_IND", \
"FAC_CFM", "UMSG_IND", "STA_IND", "SUSP_IND", "RESM_IND", "SSP_STA_CFM", "INVALID"
FTDM_STR2ENUM_P(ftdm_str2sngss7_event, ftdm_sngss7_event2str, sng_event_type_t)
typedef enum {
SNG_BIT_A = (1 << 0),
@ -117,6 +138,12 @@ typedef enum {
SNG_CALLING = 2
} sng_addr_type_t;
typedef enum {
SNG_GEN_CFG_STATUS_INIT = 0,
SNG_GEN_CFG_STATUS_PENDING = 1,
SNG_GEN_CFG_STATUS_DONE = 2
} nsg_gen_cfg_type_t;
typedef struct sng_mtp2_error_type {
int init;
char sng_type[MAX_NAME_LEN];
@ -176,6 +203,21 @@ typedef struct sng_mtp2_link {
uint32_t t7;
} sng_mtp2_link_t;
/* defining glare handling methods:
SNGSS7_GLARE_PC:
higher PointCode controls even number CIC
lower PointCode controls odd number CIC
SNGSS7_GLARE_DOWN:
always give control to the other side
SNGSS7_GLARE_CONTROL:
always trying to control
*/
typedef enum {
SNGSS7_GLARE_PC = 0,
SNGSS7_GLARE_DOWN,
SNGSS7_GLARE_CONTROL
} sng_glare_resolution;
typedef struct sng_mtp3_link {
char name[MAX_NAME_LEN];
uint32_t flags;
@ -328,6 +370,7 @@ typedef struct sng_isup_ckt {
uint32_t clg_nadi;
uint32_t cld_nadi;
uint8_t rdnis_nadi;
uint32_t loc_nadi;
/* Generic Number defaults */
uint8_t gn_nmbqual; /* Number Qualifier */
@ -339,8 +382,11 @@ typedef struct sng_isup_ckt {
/* END - Generic Number defaults */
uint32_t min_digits;
uint8_t itx_auto_reply;
uint32_t transparent_iam_max_size;
uint8_t transparent_iam;
uint8_t cpg_on_progress_media;
uint8_t cpg_on_progress;
uint8_t itx_auto_reply;
void *obj;
uint16_t t3;
uint32_t t10;
@ -351,6 +397,7 @@ typedef struct sng_isup_ckt {
uint16_t t16;
uint16_t t17;
uint32_t t35;
uint32_t t39;
uint16_t tval;
} sng_isup_ckt_t;
@ -404,11 +451,34 @@ typedef struct sng_relay {
uint32_t procId;
} sng_relay_t;
/**********************************************
sctp structures and data definitions
**********************************************/
typedef struct sng_sctp_gen_cfg {
} sng_sctp_gen_cfg_t;
typedef struct sng_sctp_link {
char name[MAX_NAME_LEN];
uint32_t flags;
uint32_t id;
uint32_t port;
uint32_t numSrcAddr;
uint32_t srcAddrList[SCT_MAX_NET_ADDRS+1];
} sng_sctp_link_t;
typedef struct sng_sctp_cfg {
sng_sctp_gen_cfg_t genCfg;
sng_sctp_link_t linkCfg[MAX_SCTP_LINK+1];
} sng_sctp_cfg_t;
typedef struct sng_ss7_cfg {
uint32_t spc;
uint32_t procId;
char license[MAX_PATH];
char signature[MAX_PATH];
char license[MAX_SNGSS7_PATH];
char signature[MAX_SNGSS7_PATH];
uint32_t transparent_iam_max_size;
uint32_t flags;
sng_relay_t relay[MAX_RELAY_CHANNELS+1];
@ -421,6 +491,10 @@ typedef struct sng_ss7_cfg {
sng_isup_ckt_t isupCkt[10000]; /* KONRAD - only need 2000 ( and 0-1000 aren't used) since other servers are registerd else where */
sng_nsap_t nsap[MAX_NSAPS+1];
sng_isap_t isap[MAX_ISAPS+1];
sng_glare_resolution glareResolution;
uint32_t force_inr;
sng_m2ua_gbl_cfg_t g_m2ua_cfg;
sng_sctp_cfg_t sctpCfg;
} sng_ss7_cfg_t;
typedef struct ftdm_sngss7_data {
@ -433,6 +507,14 @@ typedef struct ftdm_sngss7_data {
fio_signal_cb_t sig_cb;
} ftdm_sngss7_data_t;
typedef enum{
SNG_SS7_OPR_MODE_NONE,
SNG_SS7_OPR_MODE_M2UA_SG,
SNG_SS7_OPR_MODE_ISUP,
}ftdm_sngss7_operating_modes_e;
typedef ftdm_sngss7_operating_modes_e ftdm_sngss7_opr_mode;
typedef struct sngss7_timer_data {
ftdm_timer_id_t hb_timer_id;
int beat;
@ -472,10 +554,14 @@ typedef struct sngss7_chan_data {
sngss7_glare_data_t glare;
sngss7_timer_data_t t35;
sngss7_timer_data_t t10;
sngss7_timer_data_t t39;
sngss7_group_data_t rx_grs;
sngss7_group_data_t rx_gra;
sngss7_group_data_t tx_grs;
sngss7_group_data_t ucic;
ftdm_queue_t *event_queue;
struct sngss7_chan_data *peer_data;
uint8_t peer_event_transfer_cnt;
} sngss7_chan_data_t;
#define SNGSS7_RX_GRS_PENDING (1 << 0)
@ -533,6 +619,18 @@ typedef enum {
FLAG_INFID_RESUME = (1 << 14),
FLAG_INFID_PAUSED = (1 << 15),
FLAG_SENT_ACM = (1 << 16),
FLAG_SENT_CPG = (1 << 17),
FLAG_SUS_RECVD = (1 << 18),
FLAG_T6_CANCELED = (1 << 19),
FLAG_INR_TX = (1 << 20),
FLAG_INR_SENT = (1 << 21),
FLAG_INR_RX = (1 << 22),
FLAG_INR_RX_DN = (1 << 23),
FLAG_INF_TX = (1 << 24),
FLAG_INF_SENT = (1 << 25),
FLAG_INF_RX = (1 << 26),
FLAG_INF_RX_DN = (1 << 27),
FLAG_FULL_NUMBER = (1 << 28),
FLAG_RELAY_DOWN = (1 << 30),
FLAG_CKT_RECONFIG = (1 << 31)
} sng_ckt_flag_t;
@ -541,20 +639,28 @@ typedef enum {
"RX_RSC", \
"TX_RSC", \
"TX_RSC_REQ_SENT", \
"TX_RSC_RSP_RECIEVED", \
"TX_RSC_RSP_RECEIVED", \
"RX_GRS", \
"RX_GRS_DONE", \
"RX_GRS_CMPLT", \
"GRS_BASE", \
"TX_GRS", \
"TX_GRS_REQ_SENT", \
"TX_GRS_RSP_RECIEVED", \
"TX_GRS_RSP_RECEIVED", \
"REMOTE_REL", \
"LOCAL_REL", \
"GLARE", \
"INF_RESUME", \
"INF_PAUSED", \
"TX_ACM_SENT" \
"TX_INR" \
"INR_SENT" \
"RX_INR" \
"RX_INR_DN" \
"TX_INF" \
"INF SENT" \
"RX_INF" \
"RX_INF_DN" \
"RELAY_DOWN", \
"CKT_RECONFIG"
FTDM_STR2ENUM_P(ftmod_ss7_ckt_state2flag, ftmod_ss7_ckt_flag2str, sng_ckt_flag_t)
@ -588,7 +694,7 @@ typedef enum {
FLAG_GRP_HW_UNBLK_TX = (1 << 24),
FLAG_GRP_HW_UNBLK_TX_DN = (1 << 25),
FLAG_GRP_MN_UNBLK_TX = (1 << 26),
FLAG_GRP_MN_UNBLK_TX_DN = (1 << 27)
FLAG_GRP_MN_UNBLK_TX_DN = (1 << 27),
} sng_ckt_block_flag_t;
#define BLK_FLAGS_STRING \
@ -652,11 +758,27 @@ typedef enum {
SNGSS7_CC_PRESENT = (1 << 12),
SNGSS7_CC_STARTED = (1 << 13),
SNGSS7_TUCL_PRESENT = (1 << 14),
SNGSS7_TUCL_STARTED = (1 << 15),
SNGSS7_SCTP_PRESENT = (1 << 16),
SNGSS7_SCTP_STARTED = (1 << 17),
SNGSS7_M2UA_PRESENT = (1 << 18),
SNGSS7_M2UA_STARTED = (1 << 19),
SNGSS7_M2UA_EP_OPENED = (1 << 20),
SNGSS7_M2UA_INIT_ASSOC_DONE = (1 << 21),
SNGSS7_NIF_PRESENT = (1 << 22),
SNGSS7_NIF_STARTED = (1 << 23),
} sng_task_flag_t;
/******************************************************************************/
/* GLOBALS ********************************************************************/
extern ftdm_sngss7_data_t g_ftdm_sngss7_data;
extern ftdm_sngss7_opr_mode g_ftdm_operating_mode;
extern sng_ssf_type_t sng_ssf_type_map[];
extern sng_switch_type_t sng_switch_type_map[];
extern sng_link_type_t sng_link_type_map[];
@ -679,6 +801,10 @@ void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta);
void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta);
void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta);
void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta);
void handle_sng_m2ua_alarm(Pst *pst, MwMgmt *sta);
void handle_sng_nif_alarm(Pst *pst, NwMgmt *sta);
void handle_sng_tucl_alarm(Pst *pst, HiMngmt *sta);
void handle_sng_sctp_alarm(Pst *pst, SbMgmt *sta);
/* in ftmod_sangoma_ss7_relay.c */
ftdm_status_t handle_relay_connect(RyMngmt *sta);
@ -731,7 +857,9 @@ int ftmod_ss7_enable_grp_mtp3Link(uint32_t procId);
int ftmod_ss7_disable_grp_mtp2Link(uint32_t procId);
int ftmod_ss7_block_isup_ckt(uint32_t cktId);
#define ftmod_ss7_block_isup_ckt(x) __ftmod_ss7_block_isup_ckt(x,FTDM_TRUE)
#define ftmod_ss7_block_isup_ckt_nowait(x) __ftmod_ss7_block_isup_ckt(x,FTDM_FALSE)
int __ftmod_ss7_block_isup_ckt(uint32_t cktId, ftdm_bool_t wait);
int ftmod_ss7_unblock_isup_ckt(uint32_t cktId);
@ -767,6 +895,9 @@ void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan);
void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan);
void ft_to_sngss7_itx (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_txa (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_inr(ftdm_channel_t * ftdmchan);
void ft_to_sngss7_inf(ftdm_channel_t *ftdmchan, SiCnStEvnt *inr);
/* in ftmod_sangoma_ss7_in.c */
@ -835,15 +966,27 @@ ftdm_status_t copy_cdPtyNum_from_sngss7(ftdm_channel_t *ftdmchan, SiCdPtyNum *cd
ftdm_status_t copy_cdPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCdPtyNum *cdPtyNum);
ftdm_status_t copy_redirgNum_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *redirgNum);
ftdm_status_t copy_redirgNum_from_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *redirgNum);
ftdm_status_t copy_redirgInfo_from_sngss7(ftdm_channel_t *ftdmchan, SiRedirInfo *redirInfo);
ftdm_status_t copy_redirgInfo_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirInfo *redirInfo);
ftdm_status_t copy_ocn_to_sngss7(ftdm_channel_t *ftdmchan, SiOrigCdNum *origCdNum);
ftdm_status_t copy_ocn_from_sngss7(ftdm_channel_t *ftdmchan, SiOrigCdNum *origCdNum);
ftdm_status_t copy_access_transport_from_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt);
ftdm_status_t copy_access_transport_to_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt);
ftdm_status_t copy_locPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *locPtyNum);
ftdm_status_t copy_locPtyNum_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *locPtyNum);
ftdm_status_t copy_genNmb_to_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb);
ftdm_status_t copy_genNmb_from_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb);
ftdm_status_t copy_cgPtyCat_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat);
ftdm_status_t copy_cgPtyCat_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat);
ftdm_status_t copy_accTrnspt_to_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt);
ftdm_status_t copy_natConInd_to_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd);
ftdm_status_t copy_fwdCallInd_hex_from_sngss7(ftdm_channel_t *ftdmchan, SiFwdCallInd *fwdCallInd);
ftdm_status_t copy_fwdCallInd_to_sngss7(ftdm_channel_t *ftdmchan, SiFwdCallInd *fwdCallInd);
ftdm_status_t copy_txMedReq_to_sngss7(ftdm_channel_t *ftdmchan, SiTxMedReq *txMedReq);
ftdm_status_t copy_usrServInfoA_to_sngss7(ftdm_channel_t *ftdmchan, SiUsrServInfo *usrServInfoA);
ftdm_status_t copy_NatureOfConnection_from_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd );
ftdm_status_t copy_NatureOfConnection_to_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd);
ftdm_status_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven);
ftdm_status_t append_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven);
@ -889,6 +1032,8 @@ 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);
void handle_isup_t39(void *userdata);
/******************************************************************************/
@ -910,9 +1055,9 @@ if (ftdmchan->state == new_state) { \
#define SS7_INFO_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_INFO, msg , ##args)
#define SS7_WARN_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_WARNING, msg , ##args)
#define SS7_ERROR_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_ERROR, msg , ##args)
#define SS7_CTRIT_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_CRIT, msg , ##args)
#define SS7_CRIT_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_CRIT, msg , ##args)
#ifdef KONRAD_DEVEL
#ifdef SS7_CODE_DEVEL
#define SS7_DEVEL_DEBUG(a,...) ftdm_log(FTDM_LOG_DEBUG,a,##__VA_ARGS__ );
#else
#define SS7_DEVEL_DEBUG(a,...)
@ -1039,6 +1184,40 @@ if (ftdmchan->state == new_state) { \
#define sngss7_clear_options(obj, option) ((obj)->options &= ~(option))
#define sngss7_set_options(obj, option) ((obj)->options |= (option))
#define sngss7_tx_block_status_clear(obj) (!sngss7_test_ckt_blk_flag(obj, (FLAG_CKT_MN_BLOCK_TX | \
FLAG_CKT_MN_BLOCK_TX_DN | \
FLAG_GRP_MN_BLOCK_TX | \
FLAG_GRP_MN_BLOCK_TX_DN | \
FLAG_GRP_HW_BLOCK_TX | \
FLAG_GRP_HW_BLOCK_TX_DN | \
FLAG_GRP_HW_UNBLK_TX | \
FLAG_CKT_MN_UNBLK_TX )))
#define sngss7_block_status_clear(obj) (obj->blk_flags == 0)
#define sngss7_reset_status_clear(obj) (!sngss7_test_ckt_flag(obj, (FLAG_RESET_TX | \
FLAG_RESET_RX | \
FLAG_GRP_RESET_TX | \
FLAG_GRP_RESET_RX )))
#define sngss7_tx_reset_sent(obj) ((sngss7_test_ckt_flag(obj, (FLAG_RESET_TX)) && \
sngss7_test_ckt_flag(obj, (FLAG_RESET_SENT))) || \
(sngss7_test_ckt_flag(obj, (FLAG_GRP_RESET_TX)) && \
sngss7_test_ckt_flag(obj, (FLAG_GRP_RESET_SENT))))
#define sngss7_tx_reset_status_pending(obj) (sngss7_test_ckt_flag(obj, (FLAG_RESET_TX)) || sngss7_test_ckt_flag(obj, (FLAG_GRP_RESET_TX)))
#define sngss7_channel_status_clear(obj) ((sngss7_block_status_clear(obj)) && \
(sngss7_reset_status_clear(obj)) && \
(!sngss7_test_ckt_flag((obj),FLAG_INFID_PAUSED)))
#define sngss7_tx_reset_restart(obj) do { clear_tx_grs_flags((obj)); \
clear_tx_grs_data((obj)); \
clear_tx_rsc_flags((obj)); \
sngss7_set_ckt_flag((obj), (FLAG_RESET_TX)); \
} while (0);
#ifdef SMG_RELAY_DBG
#define SS7_RELAY_DBG(a,...) printf(a"\n", ##__VA_ARGS__)

View File

@ -44,8 +44,11 @@
/* FUNCTIONS ******************************************************************/
void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
{
const char *var = NULL;
SiConEvnt iam;
ftdm_bool_t native_going_up = FTDM_FALSE;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;;
sngss7_event_data_t *event_clone = NULL;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
@ -55,9 +58,113 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
memset (&iam, 0x0, sizeof (iam));
if (sngss7_info->circuit->transparent_iam &&
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) {
ftdm_span_t *peer_span = NULL;
ftdm_channel_t *peer_chan = NULL;
sngss7_chan_data_t *peer_info = NULL;
var = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "sigbridge_peer");
ftdm_get_channel_from_string(var, &peer_span, &peer_chan);
if (!peer_chan) {
SS7_ERROR_CHAN(ftdmchan, "Failed to find sigbridge peer from string '%s'\n", var);
} else {
if (peer_span->signal_type != FTDM_SIGTYPE_SS7) {
SS7_ERROR_CHAN(ftdmchan, "Peer channel '%s' has different signaling type %d'\n",
var, peer_span->signal_type);
} else {
peer_info = peer_chan->call_data;
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Starting native bridge with peer CIC %d\n",
sngss7_info->circuit->cic, peer_info->circuit->cic);
/* retrieve only first message from the others guys queue (must be IAM) */
event_clone = ftdm_queue_dequeue(peer_info->event_queue);
/* make each one of us aware of the native bridge */
peer_info->peer_data = sngss7_info;
sngss7_info->peer_data = peer_info;
/* Go to up until release comes, note that state processing is done different and much simpler when there is a peer,
We can't go to UP state right away yet though, so do not set the state to UP here, wait until the end of this function
because moving from one state to another causes the ftdmchan->usrmsg structure to be wiped
and we still need those variables for further IAM processing */
native_going_up = FTDM_TRUE;
}
}
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) {
if (!event_clone) {
SS7_ERROR_CHAN(ftdmchan, "No IAM event clone in peer queue!%s\n", "");
} else if (event_clone->event_id != SNGSS7_CON_IND_EVENT) {
/* first message in the queue should ALWAYS be an IAM */
SS7_ERROR_CHAN(ftdmchan, "Invalid initial peer message type '%d'\n", event_clone->event_id);
} else {
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged, dialing %s)\n", sngss7_info->circuit->cic, caller_data->dnis.digits);
/* copy original incoming IAM */
memcpy(&iam, &event_clone->event.siConEvnt, sizeof(iam));
/* Change DNIS to whatever was specified, do not change NADI or anything else! */
copy_tknStr_to_sngss7(caller_data->dnis.digits, &iam.cdPtyNum.addrSig, &iam.cdPtyNum.oddEven);
/* SPIROU certification hack
If the IAM already contain RDINF, just increment the count and set the RDNIS digits
otherwise, honor RDNIS and RDINF stuff coming from the user */
if (iam.redirInfo.eh.pres == PRSNT_NODEF) {
const char *val = NULL;
if (iam.redirInfo.redirCnt.pres) {
iam.redirInfo.redirCnt.val++;
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged), redirect count incremented = %d\n", sngss7_info->circuit->cic, iam.redirInfo.redirCnt.val);
}
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_digits");
if (!ftdm_strlen_zero(val)) {
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged), found user supplied RDNIS digits = %s\n", sngss7_info->circuit->cic, val);
copy_tknStr_to_sngss7((char*)val, &iam.redirgNum.addrSig, &iam.redirgNum.oddEven);
} else {
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged), not found user supplied RDNIS digits\n", sngss7_info->circuit->cic);
}
} else {
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged), redirect info not present, attempting to copy user supplied values\n", sngss7_info->circuit->cic);
/* Redirecting Number */
copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum);
/* Redirecting Information */
copy_redirgInfo_to_sngss7(ftdmchan, &iam.redirInfo);
}
if (iam.origCdNum.eh.pres != PRSNT_NODEF) {
/* Original Called Number */
copy_ocn_to_sngss7(ftdmchan, &iam.origCdNum);
}
copy_access_transport_to_sngss7(ftdmchan, &iam.accTrnspt);
}
} else if (sngss7_info->circuit->transparent_iam &&
sngss7_retrieve_iam(ftdmchan, &iam) == FTDM_SUCCESS) {
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Transparent)\n", sngss7_info->circuit->cic);
/* Called Number information */
copy_cdPtyNum_to_sngss7(ftdmchan, &iam.cdPtyNum);
/* Redirecting Number */
copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum);
/* Redirecting Information */
copy_redirgInfo_to_sngss7(ftdmchan, &iam.redirInfo);
/* Location Number information */
copy_locPtyNum_to_sngss7(ftdmchan, &iam.cgPtyNum1);
/* Forward Call Indicators */
copy_fwdCallInd_to_sngss7(ftdmchan, &iam.fwdCallInd);
/* Original Called Number */
copy_ocn_to_sngss7(ftdmchan, &iam.origCdNum);
copy_access_transport_to_sngss7(ftdmchan, &iam.accTrnspt);
copy_NatureOfConnection_to_sngss7(ftdmchan, &iam.natConInd);
} else {
/* Nature of Connection Indicators */
copy_natConInd_to_sngss7(ftdmchan, &iam.natConInd);
@ -79,6 +186,9 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
/* Calling Number information */
copy_cgPtyNum_to_sngss7(ftdmchan, &iam.cgPtyNum);
/* Location Number information */
copy_locPtyNum_to_sngss7(ftdmchan, &iam.cgPtyNum1);
/* Generic Number information */
copy_genNmb_to_sngss7(ftdmchan, &iam.genNmb);
@ -88,15 +198,30 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
/* Redirecting Number */
copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum);
/* Access Transport */
copy_accTrnspt_to_sngss7(ftdmchan, &iam.accTrnspt);
/* Redirecting Information */
copy_redirgInfo_to_sngss7(ftdmchan, &iam.redirInfo);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM clg = \"%s\" (NADI=%d), cld = \"%s\" (NADI=%d)\n",
/* Original Called Number */
copy_ocn_to_sngss7(ftdmchan, &iam.origCdNum);
/* Access Transport - old implementation, taking from channel variable of ss7_clg_subaddr */
copy_accTrnspt_to_sngss7(ftdmchan, &iam.accTrnspt);
/* Access Transport - taking from channel variable of ss7_access_transport_urlenc.
This will overwirte the IE value set be above old implementation.
*/
copy_access_transport_to_sngss7(ftdmchan, &iam.accTrnspt);
copy_NatureOfConnection_to_sngss7(ftdmchan, &iam.natConInd);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM clg = \"%s\" (NADI=%d), cld = \"%s\" (NADI=%d), loc = %s (NADI=%d)\n",
sngss7_info->circuit->cic,
ftdmchan->caller_data.cid_num.digits,
iam.cgPtyNum.natAddrInd.val,
ftdmchan->caller_data.dnis.digits,
iam.cdPtyNum.natAddrInd.val);
iam.cdPtyNum.natAddrInd.val,
ftdmchan->caller_data.loc.digits,
iam.cgPtyNum1.natAddrInd.val);
}
sng_cc_con_request (sngss7_info->spId,
@ -106,16 +231,124 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
&iam,
0);
if (native_going_up) {
/*
Note that this function (ft_to_sngss7_iam) is run within the main SS7 processing loop in
response to the DIALING state handler, we can set the state to UP here and that will
implicitly complete the DIALING state, but we *MUST* also advance the state handler
right away for a native bridge, otherwise, the processing state function (ftdm_sangoma_ss7_process_state_change)
will complete the state without having executed the handler for FTDM_CHANNEL_STATE_UP, and we won't notify
the user sending FTDM_SIGEVENT_UP which can cause the application to misbehave (ie, no audio) */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
ftdm_channel_advance_states(ftdmchan);
}
ftdm_safe_free(event_clone);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
void ft_to_sngss7_inf(ftdm_channel_t *ftdmchan, SiCnStEvnt *inr)
{
SiCnStEvnt evnt;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
memset (&evnt, 0x0, sizeof (evnt));
evnt.infoInd.eh.pres = PRSNT_NODEF;
evnt.infoInd.cgPtyAddrRespInd.pres = PRSNT_NODEF;
evnt.infoInd.cgPtyCatRespInd.pres = PRSNT_NODEF;
evnt.infoInd.chrgInfoRespInd.pres = PRSNT_NODEF;
evnt.infoInd.chrgInfoRespInd.val = 0;
evnt.infoInd.solInfoInd.pres = PRSNT_NODEF;
evnt.infoInd.solInfoInd.val = 0;
evnt.infoInd.holdProvInd.pres = PRSNT_NODEF;
evnt.infoInd.holdProvInd.val = 0;
evnt.infoInd.spare.pres = PRSNT_NODEF;
evnt.infoInd.spare.val = 0;
if (inr->infoReqInd.eh.pres == PRSNT_NODEF) {
if ((inr->infoReqInd.holdingInd.pres == PRSNT_NODEF) && (inr->infoReqInd.holdingInd.val == HOLD_REQ)) {
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Received INR requesting holding information. Holding is not supported in INF.\n", sngss7_info->circuit->cic);
}
if ((inr->infoReqInd.chrgInfoReqInd.pres == PRSNT_NODEF) && (inr->infoReqInd.chrgInfoReqInd.val == CHRGINFO_REQ)) {
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Received INR requesting charging information. Charging is not supported in INF.\n", sngss7_info->circuit->cic);
}
if ((inr->infoReqInd.malCaIdReqInd.pres == PRSNT_NODEF) && (inr->infoReqInd.malCaIdReqInd.val == CHRGINFO_REQ)) {
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Received INR requesting malicious call id. Malicious call id is not supported in INF.\n", sngss7_info->circuit->cic);
}
if ((inr->infoReqInd.cgPtyAdReqInd.pres == PRSNT_NODEF) && (inr->infoReqInd.cgPtyAdReqInd.val == CGPRTYADDREQ_REQ)) {
evnt.infoInd.cgPtyAddrRespInd.val=CGPRTYADDRESP_INCL;
copy_cgPtyNum_to_sngss7 (ftdmchan, &evnt.cgPtyNum);
} else {
evnt.infoInd.cgPtyAddrRespInd.val=CGPRTYADDRESP_NOTINCL;
}
if ((inr->infoReqInd.cgPtyCatReqInd.pres == PRSNT_NODEF) && (inr->infoReqInd.cgPtyCatReqInd.val == CGPRTYCATREQ_REQ)) {
evnt.infoInd.cgPtyCatRespInd.val = CGPRTYCATRESP_INCL;
copy_cgPtyCat_to_sngss7 (ftdmchan, &evnt.cgPtyCat);
} else {
evnt.infoInd.cgPtyCatRespInd.val = CGPRTYCATRESP_NOTINCL;
}
}
else {
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Received INR with no information request. Sending back default INF.\n", sngss7_info->circuit->cic);
}
sng_cc_inf(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&evnt,
INFORMATION);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx INF\n", sngss7_info->circuit->cic);
}
void ft_to_sngss7_inr(ftdm_channel_t *ftdmchan)
{
SiCnStEvnt evnt;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
memset (&evnt, 0x0, sizeof (evnt));
evnt.infoReqInd.eh.pres = PRSNT_NODEF;
evnt.infoReqInd.cgPtyAdReqInd.pres = PRSNT_NODEF;
evnt.infoReqInd.cgPtyAdReqInd.val=CGPRTYADDREQ_REQ;
evnt.infoReqInd.holdingInd.pres = PRSNT_NODEF;
evnt.infoReqInd.holdingInd.val = HOLD_REQ;
evnt.infoReqInd.cgPtyCatReqInd.pres = PRSNT_NODEF;
evnt.infoReqInd.cgPtyCatReqInd.val = CGPRTYCATREQ_REQ;
evnt.infoReqInd.chrgInfoReqInd.pres = PRSNT_NODEF;
evnt.infoReqInd.chrgInfoReqInd.val = CHRGINFO_REQ;
evnt.infoReqInd.malCaIdReqInd.pres = PRSNT_NODEF;
evnt.infoReqInd.malCaIdReqInd.val = MLBG_INFOREQ;
sng_cc_inr(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&evnt,
INFORMATREQ);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx INR\n", sngss7_info->circuit->cic);
}
void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiCnStEvnt acm;
const char *backwardInd = NULL;
memset (&acm, 0x0, sizeof (acm));
@ -133,8 +366,16 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
acm.bckCallInd.intInd.val = INTIND_NOINTW;
acm.bckCallInd.end2EndInfoInd.pres = PRSNT_NODEF;
acm.bckCallInd.end2EndInfoInd.val = E2EINF_NOINFO;
acm.bckCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF;
acm.bckCallInd.isdnUsrPrtInd.val = ISUP_USED;
acm.bckCallInd.isdnUsrPrtInd.val = ISUP_NOTUSED;
backwardInd = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "acm_bi_iup");
if (!ftdm_strlen_zero(backwardInd)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied backward indicator ISDN user part indicator ACM, value \"%s\"\n", backwardInd);
if (atoi(backwardInd) != 0 ) {
acm.bckCallInd.isdnUsrPrtInd.val = ISUP_USED;
}
}
acm.bckCallInd.holdInd.pres = PRSNT_NODEF;
acm.bckCallInd.holdInd.val = HOLD_NOTREQD;
acm.bckCallInd.isdnAccInd.pres = PRSNT_NODEF;
@ -241,6 +482,7 @@ void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan)
/******************************************************************************/
void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan)
{
const char *loc_ind = NULL;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
@ -250,7 +492,15 @@ void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan)
rel.causeDgn.eh.pres = PRSNT_NODEF;
rel.causeDgn.location.pres = PRSNT_NODEF;
rel.causeDgn.location.val = 0x01;
loc_ind = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rel_loc");
if (!ftdm_strlen_zero(loc_ind)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied location indicator in REL, value \"%s\"\n", loc_ind);
rel.causeDgn.location.val = atoi(loc_ind);
} else {
rel.causeDgn.location.val = 0x01;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied location indicator in REL, using 0x01\"%s\"\n", "");
}
rel.causeDgn.cdeStand.pres = PRSNT_NODEF;
rel.causeDgn.cdeStand.val = 0x00;
rel.causeDgn.recommend.pres = NOTPRSNT;
@ -260,10 +510,10 @@ void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan)
/* send the REL request to LibSngSS7 */
sng_cc_rel_request (1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&rel);
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&rel);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx REL cause=%d \n",
sngss7_info->circuit->cic,
@ -518,8 +768,6 @@ void ft_to_sngss7_grs (ftdm_channel_t *fchan)
cinfo->circuit->cic,
(cinfo->circuit->cic + cinfo->tx_grs.range));
memset(&cinfo->tx_grs, 0, sizeof(cinfo->tx_grs));
sngss7_set_ckt_flag(cinfo, FLAG_GRP_RESET_SENT);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);

View File

@ -42,8 +42,6 @@
/******************************************************************************/
/* PROTOTYPES *****************************************************************/
ftdm_status_t handle_relay_connect(RyMngmt *sta);
ftdm_status_t handle_relay_disconnect(RyMngmt *sta);
/*static ftdm_status_t enable_all_ckts_for_relay(void);*/
static ftdm_status_t reconfig_all_ckts_for_relay(void);
@ -66,11 +64,9 @@ ftdm_status_t handle_relay_connect(RyMngmt *sta)
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! */
}
if (reconfig_all_ckts_for_relay()) {
SS7_ERROR("Failed to reconfigure ISUP Ckts!\n");
/* we're done....this is very bad! */
}
return FTDM_SUCCESS;
} else if (sng_relay->type == LRY_CT_TCP_SERVER) {
@ -84,23 +80,24 @@ ftdm_status_t handle_relay_connect(RyMngmt *sta)
/******************************************************************************/
ftdm_status_t handle_relay_disconnect_on_error(RyMngmt *sta)
{
SS7_DEBUG("SS7 relay disconnect on error\n");
/* check which procId is in error, if it is 1, disable the ckts */
if (sta->t.usta.s.ryErrUsta.errPid == 1 ) {
/* we've lost the server, bring down the mtp2 links */
disble_all_mtp2_sigs_for_relay();
/* we've lost the server, bring the sig status down on all ckts */
disable_all_ckts_for_relay();
/* we've lost the server, bring down the mtp2 links */
disble_all_mtp2_sigs_for_relay();
}
/* check if the channel is a server, means we just lost a MGW */
if (g_ftdm_sngss7_data.cfg.relay[sta->t.usta.s.ryErrUsta.errPid].type == LRY_CT_TCP_SERVER) {
/* we've lost the client, bring down all mtp3 links for this procId */
disable_all_sigs_for_relay(sta->t.usta.s.ryErrUsta.errPid);
/* we've lost the client, bring down all the ckts for this procId */
block_all_ckts_for_relay(sta->t.usta.s.ryErrUsta.errPid);
/* we've lost the client, bring down all mtp3 links for this procId */
disable_all_sigs_for_relay(sta->t.usta.s.ryErrUsta.errPid);
}
return FTDM_SUCCESS;
@ -110,6 +107,8 @@ ftdm_status_t handle_relay_disconnect_on_error(RyMngmt *sta)
ftdm_status_t handle_relay_disconnect_on_down(RyMngmt *sta)
{
SS7_DEBUG("SS7 relay disconnect on down\n");
/* check if the channel is a server, means we just lost a MGW */
if (g_ftdm_sngss7_data.cfg.relay[sta->t.usta.s.ryUpUsta.id].type == LRY_CT_TCP_SERVER) {
block_all_ckts_for_relay(sta->t.usta.s.ryUpUsta.id);
@ -248,7 +247,7 @@ ftdm_status_t block_all_ckts_for_relay(uint32_t procId)
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) {
/* send a block request via stack manager */
ret = ftmod_ss7_block_isup_ckt(g_ftdm_sngss7_data.cfg.isupCkt[x].id);
ret = ftmod_ss7_block_isup_ckt_nowait(g_ftdm_sngss7_data.cfg.isupCkt[x].id);
if (ret) {
SS7_INFO("Successfully BLOcked CIC:%d(ckt:%d) due to Relay failure\n",
g_ftdm_sngss7_data.cfg.isupCkt[x].cic,
@ -331,6 +330,7 @@ static ftdm_status_t unblock_all_ckts_for_relay(uint32_t procId)
}
#endif
/******************************************************************************/
/* For Emacs:
* Local Variables:

View File

@ -49,7 +49,7 @@
/******************************************************************************/
/* PROTOTYPES *****************************************************************/
void handle_isup_t35(void *userdata);
/******************************************************************************/
/* FUNCTIONS ******************************************************************/
@ -76,10 +76,13 @@ void handle_isup_t35(void *userdata)
/* end the call */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
/* kill t10 if active */
/* kill t10 t39 if active */
if (sngss7_info->t10.hb_timer_id) {
ftdm_sched_cancel_timer (sngss7_info->t10.sched, sngss7_info->t10.hb_timer_id);
}
if (sngss7_info->t39.hb_timer_id) {
ftdm_sched_cancel_timer (sngss7_info->t39.sched, sngss7_info->t39.hb_timer_id);
}
/*unlock*/
ftdm_channel_unlock(ftdmchan);
@ -108,7 +111,43 @@ void handle_isup_t10(void *userdata)
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
void handle_isup_t39(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;
/* now that we have the right channel...put a lock on it so no-one else can use it */
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 39 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 = FTDM_CAUSE_INVALID_NUMBER_FORMAT;
/* end the call */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
/* kill t10 t35 if active */
if (sngss7_info->t10.hb_timer_id) {
ftdm_sched_cancel_timer (sngss7_info->t10.sched, sngss7_info->t10.hb_timer_id);
}
if (sngss7_info->t35.hb_timer_id) {
ftdm_sched_cancel_timer (sngss7_info->t35.sched, sngss7_info->t35.hb_timer_id);
}
/*unlock*/
ftdm_channel_unlock(ftdmchan);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
/******************************************************************************/
/* For Emacs:
* Local Variables:

View File

@ -29,6 +29,12 @@
* 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:
*
* James Zhang <jzhang@sangoma.com>
*
*/
/* INCLUDE ********************************************************************/
@ -124,9 +130,13 @@ typedef struct sng_ccSpan
uint32_t clg_nadi;
uint32_t cld_nadi;
uint32_t rdnis_nadi;
uint32_t loc_nadi;
uint32_t min_digits;
uint8_t itx_auto_reply;
uint32_t transparent_iam_max_size;
uint8_t transparent_iam;
uint8_t cpg_on_progress_media;
uint8_t cpg_on_progress;
uint8_t itx_auto_reply;
uint32_t t3;
uint32_t t10;
uint32_t t12;
@ -136,6 +146,7 @@ typedef struct sng_ccSpan
uint32_t t16;
uint32_t t17;
uint32_t t35;
uint32_t t39;
uint32_t tval;
} sng_ccSpan_t;
@ -187,18 +198,20 @@ static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, i
static int ftmod_ss7_fill_in_circuits(sng_span_t *sngSpan);
static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot);
static void ftmod_ss7_set_glare_resolution (const char *method);
/******************************************************************************/
/* FUNCTIONS ******************************************************************/
int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span)
{
sng_route_t self_route;
sng_span_t sngSpan;
int i = 0;
const char *var = NULL;
const char *val = NULL;
ftdm_conf_node_t *ptr = NULL;
sng_route_t self_route;
sng_span_t sngSpan;
/* clean out the isup ckt */
memset(&sngSpan, 0x0, sizeof(sngSpan));
@ -206,11 +219,31 @@ int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *spa
/* clean out the self route */
memset(&self_route, 0x0, sizeof(self_route));
var = ftdm_parameters[i].var;
val = ftdm_parameters[i].val;
g_ftdm_operating_mode = SNG_SS7_OPR_MODE_ISUP;
/* confirm that the first parameter is the "operating-mode" */
if(!strcasecmp(var, "operating-mode")){
if(!strcasecmp(val, "ISUP")) {
g_ftdm_operating_mode = SNG_SS7_OPR_MODE_ISUP;
}
else if(!strcasecmp(val, "M2UA_SG")) {
g_ftdm_operating_mode = SNG_SS7_OPR_MODE_M2UA_SG;
} else {
SS7_DEBUG("Operating mode not specified, defaulting to ISUP\n");
}
i++;
}
var = ftdm_parameters[i].var;
val = ftdm_parameters[i].val;
ptr = (ftdm_conf_node_t *)ftdm_parameters[i].ptr;
/* confirm that the first parameter is the "confnode" */
/* confirm that the 2nd parameter is the "confnode" */
if (!strcasecmp(var, "confnode")) {
/* parse the confnode and fill in the global libsng_ss7 config structure */
if (ftmod_ss7_parse_sng_isup(ptr)) {
@ -225,28 +258,20 @@ int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *spa
}
i++;
while (ftdm_parameters[i].var != NULL) {
/**************************************************************************/
while (ftdm_parameters[i].var != NULL) {
var = ftdm_parameters[i].var;
val = ftdm_parameters[i].val;
if (!strcasecmp(var, "dialplan")) {
/**********************************************************************/
/* don't care for now */
/**********************************************************************/
} else if (!strcasecmp(var, "context")) {
/**********************************************************************/
/* don't care for now */
/**********************************************************************/
} else if (!strcasecmp(var, "ccSpanId")) {
/**********************************************************************/
} else if (!strcasecmp(var, "span-id") || !strcasecmp(var, "ccSpanId")) {
sngSpan.ccSpanId = atoi(val);
SS7_DEBUG("Found an ccSpanId = %d\n",sngSpan.ccSpanId);
/**********************************************************************/
} else {
SS7_ERROR("Unknown parameter found =\"%s\"...ignoring it!\n", var);
/**********************************************************************/
}
i++;
@ -255,10 +280,12 @@ int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *spa
/* fill the pointer to span into isupCkt */
sngSpan.span = span;
/* setup the circuits structure */
if(ftmod_ss7_fill_in_circuits(&sngSpan)) {
SS7_ERROR("Failed to fill in circuits structure!\n");
goto ftmod_ss7_parse_xml_error;
if(SNG_SS7_OPR_MODE_ISUP == g_ftdm_operating_mode){
/* setup the circuits structure */
if(ftmod_ss7_fill_in_circuits(&sngSpan)) {
SS7_ERROR("Failed to fill in circuits structure!\n");
goto ftmod_ss7_parse_xml_error;
}
}
return FTDM_SUCCESS;
@ -280,6 +307,11 @@ static int ftmod_ss7_parse_sng_isup(ftdm_conf_node_t *sng_isup)
ftdm_conf_node_t *isup_interfaces = NULL;
ftdm_conf_node_t *cc_spans = NULL;
ftdm_conf_node_t *tmp_node = NULL;
ftdm_conf_node_t *nif_ifaces = NULL;
ftdm_conf_node_t *m2ua_ifaces = NULL;
ftdm_conf_node_t *m2ua_peer_ifaces = NULL;
ftdm_conf_node_t *m2ua_clust_ifaces = NULL;
ftdm_conf_node_t *sctp_ifaces = NULL;
/* confirm that we are looking at sng_isup */
if (strcasecmp(sng_isup->name, "sng_isup")) {
@ -385,12 +417,62 @@ static int ftmod_ss7_parse_sng_isup(ftdm_conf_node_t *sng_isup)
return FTDM_FAIL;
}
/**********************************************************************/
} else if (!strcasecmp(tmp_node->name, "sng_nif_interfaces")) {
/**********************************************************************/
if (nif_ifaces == NULL) {
nif_ifaces = tmp_node;
SS7_DEBUG("Found a \"sng_nif_interfaces\" section!\n");
} else {
SS7_ERROR("Found a second \"sng_nif_interfaces\" section\n!");
return FTDM_FAIL;
}
/**********************************************************************/
} else if (!strcasecmp(tmp_node->name, "sng_m2ua_interfaces")) {
/**********************************************************************/
if (m2ua_ifaces == NULL) {
m2ua_ifaces = tmp_node;
SS7_DEBUG("Found a \"sng_m2ua_interfaces\" section!\n");
} else {
SS7_ERROR("Found a second \"sng_m2ua_interfaces\" section\n!");
return FTDM_FAIL;
}
/**********************************************************************/
} else if (!strcasecmp(tmp_node->name, "sng_m2ua_peer_interfaces")) {
/**********************************************************************/
if (m2ua_peer_ifaces == NULL) {
m2ua_peer_ifaces = tmp_node;
SS7_DEBUG("Found a \"sng_m2ua_peer_interfaces\" section!\n");
} else {
SS7_ERROR("Found a second \"sng_m2ua_peer_interfaces\" section\n!");
return FTDM_FAIL;
}
/**********************************************************************/
} else if (!strcasecmp(tmp_node->name, "sng_m2ua_cluster_interfaces")) {
/**********************************************************************/
if (m2ua_clust_ifaces == NULL) {
m2ua_clust_ifaces = tmp_node;
SS7_DEBUG("Found a \"sng_m2ua_cluster_interfaces\" section!\n");
} else {
SS7_ERROR("Found a second \"sng_m2ua_peer_interfaces\" section\n!");
return FTDM_FAIL;
}
/**********************************************************************/
} else if (!strcasecmp(tmp_node->name, "sng_sctp_interfaces")) {
/**********************************************************************/
if (sctp_ifaces == NULL) {
sctp_ifaces = tmp_node;
SS7_DEBUG("Found a <sng_sctp_interfaces> section!\n");
} else {
SS7_ERROR("Found a second <sng_sctp_interfaces> section!\n");
return FTDM_FAIL;
}
/**********************************************************************/
} else {
/**********************************************************************/
SS7_ERROR("\tFound an unknown section \"%s\"!\n", tmp_node->name);
return FTDM_FAIL;
/**********************************************************************/
}
}
/* go to the next sibling */
tmp_node = tmp_node->next;
@ -417,34 +499,92 @@ static int ftmod_ss7_parse_sng_isup(ftdm_conf_node_t *sng_isup)
return FTDM_FAIL;
}
if (ftmod_ss7_parse_mtp3_links(mtp3_links)) {
SS7_ERROR("Failed to parse \"mtp3_links\"!\n");
return FTDM_FAIL;
}
if (ftmod_ss7_parse_mtp_linksets(mtp_linksets)) {
SS7_ERROR("Failed to parse \"mtp_linksets\"!\n");
return FTDM_FAIL;
}
switch(g_ftdm_operating_mode)
{
case SNG_SS7_OPR_MODE_ISUP:
{
if (mtp3_links && ftmod_ss7_parse_mtp3_links(mtp3_links)) {
SS7_ERROR("Failed to parse \"mtp3_links\"!\n");
return FTDM_FAIL;
}
if (ftmod_ss7_parse_mtp_routes(mtp_routes)) {
SS7_ERROR("Failed to parse \"mtp_routes\"!\n");
return FTDM_FAIL;
}
if (ftmod_ss7_parse_mtp_linksets(mtp_linksets)) {
SS7_ERROR("Failed to parse \"mtp_linksets\"!\n");
return FTDM_FAIL;
}
if (ftmod_ss7_parse_isup_interfaces(isup_interfaces)) {
SS7_ERROR("Failed to parse \"isup_interfaces\"!\n");
return FTDM_FAIL;
}
if (ftmod_ss7_parse_mtp_routes(mtp_routes)) {
SS7_ERROR("Failed to parse \"mtp_routes\"!\n");
return FTDM_FAIL;
}
if (isup_interfaces && ftmod_ss7_parse_isup_interfaces(isup_interfaces)) {
SS7_ERROR("Failed to parse \"isup_interfaces\"!\n");
return FTDM_FAIL;
}
if (cc_spans && ftmod_ss7_parse_cc_spans(cc_spans)) {
SS7_ERROR("Failed to parse \"cc_spans\"!\n");
return FTDM_FAIL;
}
break;
}
case SNG_SS7_OPR_MODE_M2UA_SG:
{
if (ftmod_ss7_parse_sctp_links(sctp_ifaces) != FTDM_SUCCESS) {
SS7_ERROR("Failed to parse <sctp_links>!\n");
return FTDM_FAIL;
}
if (nif_ifaces && ftmod_ss7_parse_nif_interfaces(nif_ifaces)) {
SS7_ERROR("Failed to parse \"nif_ifaces\"!\n");
return FTDM_FAIL;
}
if (m2ua_ifaces && ftmod_ss7_parse_m2ua_interfaces(m2ua_ifaces)) {
SS7_ERROR("Failed to parse \"m2ua_ifaces\"!\n");
return FTDM_FAIL;
}
if (m2ua_peer_ifaces && ftmod_ss7_parse_m2ua_peer_interfaces(m2ua_peer_ifaces)) {
SS7_ERROR("Failed to parse \"m2ua_peer_ifaces\"!\n");
return FTDM_FAIL;
}
if (m2ua_clust_ifaces && ftmod_ss7_parse_m2ua_clust_interfaces(m2ua_clust_ifaces)) {
SS7_ERROR("Failed to parse \"m2ua_clust_ifaces\"!\n");
return FTDM_FAIL;
}
break;
}
default:
SS7_ERROR("Invalid operating mode[%d]\n",g_ftdm_operating_mode);
break;
if (ftmod_ss7_parse_cc_spans(cc_spans)) {
SS7_ERROR("Failed to parse \"cc_spans\"!\n");
return FTDM_FAIL;
}
return FTDM_SUCCESS;
}
static void ftmod_ss7_set_glare_resolution (const char *method)
{
sng_glare_resolution iMethod=SNGSS7_GLARE_PC;
if (!method || (strlen (method) <=0) ) {
SS7_ERROR( "Wrong glare resolution parameter, using default. \n" );
} else {
if (!strcasecmp( method, "PointCode")) {
iMethod = SNGSS7_GLARE_PC;
} else if (!strcasecmp( method, "Down")) {
iMethod = SNGSS7_GLARE_DOWN;
} else if (!strcasecmp( method, "Control")) {
iMethod = SNGSS7_GLARE_CONTROL;
} else {
SS7_ERROR( "Wrong glare resolution parameter, using default. \n" );
iMethod = SNGSS7_GLARE_PC;
}
}
g_ftdm_sngss7_data.cfg.glareResolution = iMethod;
}
/******************************************************************************/
static int ftmod_ss7_parse_sng_gen(ftdm_conf_node_t *sng_gen)
{
@ -452,31 +592,41 @@ static int ftmod_ss7_parse_sng_gen(ftdm_conf_node_t *sng_gen)
int num_parms = sng_gen->n_parameters;
int i = 0;
/* Set the transparent_iam_max_size to default value */
g_ftdm_sngss7_data.cfg.transparent_iam_max_size=800;
g_ftdm_sngss7_data.cfg.force_inr = 0;
/* extract all the information from the parameters */
for (i = 0; i < num_parms; i++) {
/**************************************************************************/
if (!strcasecmp(parm->var, "procId")) {
/**********************************************************************/
g_ftdm_sngss7_data.cfg.procId = atoi(parm->val);
SS7_DEBUG("Found a procId = %d\n", g_ftdm_sngss7_data.cfg.procId);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "license")) {
/**********************************************************************/
strcpy(g_ftdm_sngss7_data.cfg.license, parm->val);
strcpy(g_ftdm_sngss7_data.cfg.signature, parm->val);
strcat(g_ftdm_sngss7_data.cfg.signature, ".sig");
}
else if (!strcasecmp(parm->var, "license")) {
ftdm_set_string(g_ftdm_sngss7_data.cfg.license, parm->val);
snprintf(g_ftdm_sngss7_data.cfg.signature, sizeof(g_ftdm_sngss7_data.cfg.signature), "%s.sig", parm->val);
SS7_DEBUG("Found license file = %s\n", g_ftdm_sngss7_data.cfg.license);
SS7_DEBUG("Found signature file = %s\n", g_ftdm_sngss7_data.cfg.signature);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "transparent_iam_max_size")) {
}
else if (!strcasecmp(parm->var, "transparent_iam_max_size")) {
g_ftdm_sngss7_data.cfg.transparent_iam_max_size = atoi(parm->val);
SS7_DEBUG("Found a transparent_iam max size = %d\n", g_ftdm_sngss7_data.cfg.transparent_iam_max_size);
} else {
/**********************************************************************/
}
else if (!strcasecmp(parm->var, "glare-reso")) {
ftmod_ss7_set_glare_resolution (parm->val);
SS7_DEBUG("Found glare resolution configuration = %d %s\n", g_ftdm_sngss7_data.cfg.glareResolution, parm->val );
}
else if (!strcasecmp(parm->var, "force-inr")) {
if (ftdm_true(parm->val)) {
g_ftdm_sngss7_data.cfg.force_inr = 1;
} else {
g_ftdm_sngss7_data.cfg.force_inr = 0;
}
SS7_DEBUG("Found INR force configuration = %s\n", parm->val );
}
else {
SS7_ERROR("Found an invalid parameter \"%s\"!\n", parm->val);
return FTDM_FAIL;
/**********************************************************************/
}
/* move to the next parmeter */
@ -1845,12 +1995,14 @@ static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span)
int flag_clg_nadi = 0;
int flag_cld_nadi = 0;
int flag_rdnis_nadi = 0;
int flag_loc_nadi = 0;
int i;
int ret;
/* initalize the ccSpan structure */
memset(&sng_ccSpan, 0x0, sizeof(sng_ccSpan));
/* confirm that we are looking at an mtp_link */
if (strcasecmp(cc_span->name, "cc_span")) {
SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"cc_span\"!\n",cc_span->name);
@ -1859,6 +2011,14 @@ static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span)
SS7_DEBUG("Parsing \"cc_span\"...\n");
}
/* Backward compatible.
* If cpg_on_progress_media is not in the config file
* default the cpg on progress_media to TRUE */
sng_ccSpan.cpg_on_progress_media=FTDM_TRUE;
/* If transparent_iam_max_size is not set in cc spans
* use the global value */
sng_ccSpan.transparent_iam_max_size=g_ftdm_sngss7_data.cfg.transparent_iam_max_size;
for (i = 0; i < num_parms; i++) {
/**************************************************************************/
@ -1904,6 +2064,15 @@ static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span)
sng_ccSpan.transparent_iam = ftdm_true(parm->val);
SS7_DEBUG("Found transparent_iam %d\n", sng_ccSpan.transparent_iam);
#endif
} else if (!strcasecmp(parm->var, "transparent_iam_max_size")) {
sng_ccSpan.transparent_iam_max_size = atoi(parm->val);
SS7_DEBUG("Found transparent_iam_max_size %d\n", sng_ccSpan.transparent_iam_max_size);
} else if (!strcasecmp(parm->var, "cpg_on_progress_media")) {
sng_ccSpan.cpg_on_progress_media = ftdm_true(parm->val);
SS7_DEBUG("Found cpg_on_progress_media %d\n", sng_ccSpan.cpg_on_progress_media);
} else if (!strcasecmp(parm->var, "cpg_on_progress")) {
sng_ccSpan.cpg_on_progress = ftdm_true(parm->val);
SS7_DEBUG("Found cpg_on_progress %d\n", sng_ccSpan.cpg_on_progress);
} else if (!strcasecmp(parm->var, "cicbase")) {
/**********************************************************************/
sng_ccSpan.cicbase = atoi(parm->val);
@ -1946,6 +2115,12 @@ static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span)
SS7_DEBUG("Invalid parm->value for obci_bita option\n");
}
/**********************************************************************/
} else if (!strcasecmp(parm->var, "loc_nadi")) {
/* add location reference number */
flag_loc_nadi = 1;
sng_ccSpan.loc_nadi = atoi(parm->val);
SS7_DEBUG("Found default LOC_NADI parm->value = %d\n", sng_ccSpan.loc_nadi);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "lpa_on_cot")) {
/**********************************************************************/
if (*parm->val == '1') {
@ -2002,6 +2177,11 @@ static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span)
sng_ccSpan.t35 = atoi(parm->val);
SS7_DEBUG("Found isup t35 = %d\n",sng_ccSpan.t35);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "isup.t39")) {
/**********************************************************************/
sng_ccSpan.t39 = atoi(parm->val);
SS7_DEBUG("Found isup t39 = %d\n",sng_ccSpan.t39);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "isup.tval")) {
/**********************************************************************/
sng_ccSpan.tval = atoi(parm->val);
@ -2035,6 +2215,11 @@ static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span)
sng_ccSpan.rdnis_nadi = 0x03;
}
if (!flag_loc_nadi) {
/* default the nadi value to national */
sng_ccSpan.loc_nadi = 0x03;
}
/* pull up the SSF and Switchtype from the isup interface */
sng_ccSpan.ssf = g_ftdm_sngss7_data.cfg.isupIntf[sng_ccSpan.isupInf].ssf;
sng_ccSpan.switchType = g_ftdm_sngss7_data.cfg.isupIntf[sng_ccSpan.isupInf].switchType;
@ -2723,7 +2908,7 @@ static int ftmod_ss7_fill_in_isap(sng_isap_t *sng_isap)
if (sng_isap->t1 != 0) {
g_ftdm_sngss7_data.cfg.isap[i].t1 = sng_isap->t1;
} else {
g_ftdm_sngss7_data.cfg.isap[i].t1 = 200;
g_ftdm_sngss7_data.cfg.isap[i].t1 = 150;
}
if (sng_isap->t2 != 0) {
g_ftdm_sngss7_data.cfg.isap[i].t2 = sng_isap->t2;
@ -2738,17 +2923,17 @@ static int ftmod_ss7_fill_in_isap(sng_isap_t *sng_isap)
if (sng_isap->t6 != 0) {
g_ftdm_sngss7_data.cfg.isap[i].t6 = sng_isap->t6;
} else {
g_ftdm_sngss7_data.cfg.isap[i].t6 = 200;
g_ftdm_sngss7_data.cfg.isap[i].t6 = 600;
}
if (sng_isap->t7 != 0) {
g_ftdm_sngss7_data.cfg.isap[i].t7 = sng_isap->t7;
} else {
g_ftdm_sngss7_data.cfg.isap[i].t7 = 250;
g_ftdm_sngss7_data.cfg.isap[i].t7 = 200;
}
if (sng_isap->t8 != 0) {
g_ftdm_sngss7_data.cfg.isap[i].t8 = sng_isap->t8;
} else {
g_ftdm_sngss7_data.cfg.isap[i].t8 = 120;
g_ftdm_sngss7_data.cfg.isap[i].t8 = 100;
}
if (sng_isap->t9 != 0) {
g_ftdm_sngss7_data.cfg.isap[i].t9 = sng_isap->t9;
@ -2863,7 +3048,7 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
(g_ftdm_sngss7_data.cfg.isupCkt[x].chan == count)) {
/* we are processing a circuit that already exists */
SS7_DEBUG("Found an existing circuit %d, ccSpanId=%d, chan%d\n",
SS7_DEVEL_DEBUG("Found an existing circuit %d, ccSpanId=%d, chan%d\n",
x,
ccSpan->id,
count);
@ -2872,7 +3057,7 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
flag = 1;
/* not supporting reconfig at this time */
SS7_DEBUG("Not supporting ckt reconfig at this time!\n");
SS7_DEVEL_DEBUG("Not supporting ckt reconfig at this time!\n");
goto move_along;
} else {
/* this is not the droid you are looking for */
@ -2885,6 +3070,9 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
/* prepare the global info sturcture */
ss7_info = ftdm_calloc(1, sizeof(sngss7_chan_data_t));
ss7_info->ftdmchan = NULL;
if (ftdm_queue_create(&ss7_info->event_queue, SNGSS7_CHAN_EVENT_QUEUE_SIZE) != FTDM_SUCCESS) {
SS7_CRITICAL("Failed to create ss7 cic event queue\n");
}
ss7_info->circuit = &g_ftdm_sngss7_data.cfg.isupCkt[x];
g_ftdm_sngss7_data.cfg.isupCkt[x].obj = ss7_info;
@ -2919,12 +3107,16 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
g_ftdm_sngss7_data.cfg.isupCkt[x].ssf = ccSpan->ssf;
g_ftdm_sngss7_data.cfg.isupCkt[x].cld_nadi = ccSpan->cld_nadi;
g_ftdm_sngss7_data.cfg.isupCkt[x].clg_nadi = ccSpan->clg_nadi;
g_ftdm_sngss7_data.cfg.isupCkt[x].rdnis_nadi = ccSpan->rdnis_nadi;
g_ftdm_sngss7_data.cfg.isupCkt[x].rdnis_nadi = ccSpan->rdnis_nadi;
g_ftdm_sngss7_data.cfg.isupCkt[x].loc_nadi = ccSpan->loc_nadi;
g_ftdm_sngss7_data.cfg.isupCkt[x].options = ccSpan->options;
g_ftdm_sngss7_data.cfg.isupCkt[x].switchType = ccSpan->switchType;
g_ftdm_sngss7_data.cfg.isupCkt[x].min_digits = ccSpan->min_digits;
g_ftdm_sngss7_data.cfg.isupCkt[x].itx_auto_reply = ccSpan->itx_auto_reply;
g_ftdm_sngss7_data.cfg.isupCkt[x].transparent_iam = ccSpan->transparent_iam;
g_ftdm_sngss7_data.cfg.isupCkt[x].switchType = ccSpan->switchType;
g_ftdm_sngss7_data.cfg.isupCkt[x].min_digits = ccSpan->min_digits;
g_ftdm_sngss7_data.cfg.isupCkt[x].itx_auto_reply = ccSpan->itx_auto_reply;
g_ftdm_sngss7_data.cfg.isupCkt[x].transparent_iam = ccSpan->transparent_iam;
g_ftdm_sngss7_data.cfg.isupCkt[x].transparent_iam_max_size = ccSpan->transparent_iam_max_size;
g_ftdm_sngss7_data.cfg.isupCkt[x].cpg_on_progress_media = ccSpan->cpg_on_progress_media;
g_ftdm_sngss7_data.cfg.isupCkt[x].cpg_on_progress = ccSpan->cpg_on_progress;
if (ccSpan->t3 == 0) {
g_ftdm_sngss7_data.cfg.isupCkt[x].t3 = 1200;
@ -2972,6 +3164,12 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
} else {
g_ftdm_sngss7_data.cfg.isupCkt[x].t35 = ccSpan->t35;
}
if (ccSpan->t39 == 0) {
g_ftdm_sngss7_data.cfg.isupCkt[x].t39 = 120;
} else {
g_ftdm_sngss7_data.cfg.isupCkt[x].t39 = ccSpan->t39;
}
if (ccSpan->tval == 0) {
g_ftdm_sngss7_data.cfg.isupCkt[x].tval = 10;
} else {
@ -3076,6 +3274,13 @@ static int ftmod_ss7_fill_in_circuits(sng_span_t *sngSpan)
ss7_info->t10.callback = handle_isup_t10;
ss7_info->t10.sngss7_info = ss7_info;
/* prepare the timer structures */
ss7_info->t39.sched = ((sngss7_span_data_t *)(ftdmspan->signal_data))->sched;
ss7_info->t39.counter = 1;
ss7_info->t39.beat = (isupCkt->t39) * 100; /* beat is in ms, t39 is in 100ms */
ss7_info->t39.callback = handle_isup_t39;
ss7_info->t39.sngss7_info = ss7_info;
/**************************************************************************/
} /* for (i == 1; i < ftdmspan->chan_count; i++) */

View File

@ -764,6 +764,28 @@ static FIO_COMMAND_FUNCTION(wanpipe_command)
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Disabled DTMF events\n");
#else
return FTDM_NOTIMPL;
#endif
}
break;
case FTDM_COMMAND_ENABLE_DTMF_REMOVAL:
{
#ifdef WP_API_FEATURE_LIBSNG_HWEC
int return_code = 0;
err = sangoma_hwec_set_hwdtmf_removal(ftdmchan->sockfd, ftdmchan->physical_chan_id, &return_code, 1, 0);
if (return_code) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Wanpipe failed to Disable HW-DTMF removal\n");
}
#endif
}
break;
case FTDM_COMMAND_DISABLE_DTMF_REMOVAL:
{
#ifdef WP_API_FEATURE_LIBSNG_HWEC
int return_code = 0;
err = sangoma_hwec_set_hwdtmf_removal(ftdmchan->sockfd, ftdmchan->physical_chan_id, &return_code, 0, 0);
if (return_code) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Wanpipe failed to Disable HW-DTMF removal\n");
}
#endif
}
break;

View File

@ -40,7 +40,6 @@
#ifndef FREETDM_H
#define FREETDM_H
#include "ftdm_declare.h"
#include "ftdm_call_utils.h"
@ -368,6 +367,7 @@ typedef struct ftdm_caller_data {
ftdm_number_t ani; /*!< ANI (Automatic Number Identification) */
ftdm_number_t dnis; /*!< DNIS (Dialed Number Identification Service) */
ftdm_number_t rdnis; /*!< RDNIS (Redirected Dialed Number Identification Service) */
ftdm_number_t loc; /*!< LOC (Location Reference Code) */
char aniII[FTDM_DIGITS_LIMIT]; /*! ANI II */
uint8_t screen; /*!< Screening */
uint8_t pres; /*!< Presentation*/
@ -754,6 +754,10 @@ typedef enum {
/*!< Enable/disable IO stats in the channel */
FTDM_COMMAND_SWITCH_IOSTATS = 60,
/*!< Enable/disable DTMF removal */
FTDM_COMMAND_ENABLE_DTMF_REMOVAL = 61,
FTDM_COMMAND_DISABLE_DTMF_REMOVAL = 62,
FTDM_COMMAND_COUNT,
} ftdm_command_t;
@ -1395,7 +1399,7 @@ FT_DECLARE(uint32_t) ftdm_group_get_id(const ftdm_group_t *group);
* Only use ftdm_channel_close if there is no call (incoming or outgoing) in the channel
*
* \param span_id The span id the channel belongs to
* \param chan_id Channel id of the channel you want to open
* \param chan_id Logical channel id of the channel you want to open
* \param ftdmchan Pointer to store the channel once is open
*
* \retval FTDM_SUCCESS success (the channel was found and is available)
@ -1403,6 +1407,23 @@ FT_DECLARE(uint32_t) ftdm_group_get_id(const ftdm_group_t *group);
*/
FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan);
/*!
* \brief Open a channel specifying the span id and physical chan id (required before placing a call on the channel)
*
* \warning Try using ftdm_call_place instead if you plan to place a call after opening the channel
*
* \note You must call ftdm_channel_close() or ftdm_channel_call_hangup() to release the channel afterwards
* Only use ftdm_channel_close if there is no call (incoming or outgoing) in the channel
*
* \param span_id The span id the channel belongs to
* \param chan_id Physical channel id of the channel you want to open
* \param ftdmchan Pointer to store the channel once is open
*
* \retval FTDM_SUCCESS success (the channel was found and is available)
* \retval FTDM_FAIL failure (channel was not found or not available)
*/
FT_DECLARE(ftdm_status_t) ftdm_channel_open_ph(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan);
/*!
* \brief Hunts and opens a channel specifying the span id only
*
@ -1640,6 +1661,17 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span(ftdm_span_t *span, const char *typ
*/
FT_DECLARE(ftdm_status_t) ftdm_configure_span_signaling(ftdm_span_t *span, const char *type, fio_signal_cb_t sig_cb, ftdm_conf_parameter_t *parameters);
/*!
* \brief Register callback to listen for incoming events
* \note This function should only be used when there is no signalling module
* \param span The span to register to
* \param sig_cb The callback that the signaling stack will use to notify about events
*
* \retval FTDM_SUCCESS success
* \retval FTDM_FAIL failure
*/
FT_DECLARE(ftdm_status_t) ftdm_span_register_signal_cb(ftdm_span_t *span, fio_signal_cb_t sig_cb);
/*!
* \brief Start the span signaling (must call ftdm_configure_span_signaling first)
*
@ -1655,7 +1687,6 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_signaling(ftdm_span_t *span, const
*/
FT_DECLARE(ftdm_status_t) ftdm_span_start(ftdm_span_t *span);
/*!
* \brief Stop the span signaling (must call ftdm_span_start first)
* \note certain signalings (boost signaling) does not support granular span start/stop
@ -1796,15 +1827,25 @@ FT_DECLARE(ftdm_trunk_mode_t) ftdm_span_get_trunk_mode(const ftdm_span_t *span);
FT_DECLARE(const char *) ftdm_span_get_trunk_mode_str(const ftdm_span_t *span);
/*!
* \brief Return the channel identified by the provided id
* \brief Return the channel identified by the provided logical id
*
* \param span The span where the channel belongs
* \param chanid The channel id within the span
* \param chanid The logical channel id within the span
*
* \return The channel pointer if found, NULL otherwise
*/
FT_DECLARE(ftdm_channel_t *) ftdm_span_get_channel(const ftdm_span_t *span, uint32_t chanid);
/*!
* \brief Return the channel identified by the provided physical id
*
* \param span The span where the channel belongs
* \param chanid The physical channel id within the span
*
* \return The channel pointer if found, NULL otherwise
*/
FT_DECLARE(ftdm_channel_t *) ftdm_span_get_channel_ph(const ftdm_span_t *span, uint32_t chanid);
/*! \brief Return the channel count number for the given span */
FT_DECLARE(uint32_t) ftdm_span_get_chan_count(const ftdm_span_t *span);

View File

@ -126,6 +126,9 @@
extern "C" {
#endif
#define SPAN_PENDING_CHANS_QUEUE_SIZE 1000
#define SPAN_PENDING_SIGNALS_QUEUE_SIZE 1000
#define GOTO_STATUS(label,st) status = st; goto label ;
#define ftdm_copy_string(x,y,z) strncpy(x, y, z - 1)
@ -473,6 +476,7 @@ struct ftdm_channel {
int32_t txdrops;
int32_t rxdrops;
ftdm_usrmsg_t *usrmsg;
ftdm_time_t last_state_change_time;
};
struct ftdm_span {
@ -690,6 +694,9 @@ FT_DECLARE(ftdm_status_t) ftdm_sigmsg_remove_var(ftdm_sigmsg_t *sigmsg, const ch
*/
FT_DECLARE(ftdm_status_t) ftdm_sigmsg_set_raw_data(ftdm_sigmsg_t *sigmsg, void *data, ftdm_size_t datalen);
/*! \brief Retrieve a span and channel data structure from a string in the format 'span_id:chan_id'*/
FT_DECLARE(ftdm_status_t) ftdm_get_channel_from_string(const char *string_id, ftdm_span_t **out_span, ftdm_channel_t **out_channel);
/*!
\brief Assert condition
*/

View File

@ -162,6 +162,7 @@ typedef enum {
FTDM_SIGTYPE_ANALOG,
FTDM_SIGTYPE_SANGOMABOOST,
FTDM_SIGTYPE_M3UA,
FTDM_SIGTYPE_M2UA,
FTDM_SIGTYPE_R2,
FTDM_SIGTYPE_SS7,
FTDM_SIGTYPE_GSM
@ -198,6 +199,8 @@ typedef enum {
FTDM_SPAN_NON_STOPPABLE = (1 << 13),
/* If this flag is set, then this span supports TRANSFER state */
FTDM_SPAN_USE_TRANSFER = (1 << 14),
/* This is the last flag, no more flags bigger than this */
FTDM_SPAN_MAX_FLAG = (1 << 15),
} ftdm_span_flag_t;
/*! \brief Channel supported features */
@ -266,6 +269,12 @@ typedef enum {
#define FTDM_CHANNEL_BLOCKING (1ULL << 35)
/*!< Media is digital */
#define FTDM_CHANNEL_DIGITAL_MEDIA (1ULL << 36)
/*!< Native signaling bridge is enabled */
#define FTDM_CHANNEL_NATIVE_SIGBRIDGE (1ULL << 37)
/*!< This no more flags after this flag */
#define FTDM_CHANNEL_MAX_FLAG (1ULL << 38)
/*!<When adding a new flag, need to update ftdm_io.c:channel_flag_strs */
#include "ftdm_state.h"