Merge branch 'master' into smgmaster

This commit is contained in:
Moises Silva committed 2011-07-29 16:50:22 -04:00
commit f1dc7b1ddb
398 files changed
+38753 -4037

No files matched your search

+32
View File
@@ -275,5 +275,37 @@ with the signaling protocols that you can run on top of your I/O interfaces.
-->
</span>
</r2_spans>
<!--
PRI passive tapping spans. Requires patched version from libpri at http://svn.digium.com/svn/libpri/team/moy/tap-1.4
You must also configure FreeTDM with "-with-pritap" (see ./configure help for details)
-->
<pritap_spans>
<span name="tapped1">
<!-- The peer span name used to tap the link -->
<param name="peerspan" value="tapped2"/>
<!--
Whether to mix the audio from the peerspan with the audio from this span
This is most likely what you want (and therefore the default) so you can hear
the full conversation being tapped instead of just one side
-->
<!-- <param name="mixaudio" value="yes"/> -->
<!-- switch parameters (required), where to send calls to -->
<param name="dialplan" value="XML"/>
<param name="context" value="default"/>
</span>
<span name="tapped2">
<!-- This span is linked to "tapped1" through its peerspan parameter -->
<param name="peerspan" value="tapped1"/>
<!-- <param name="mixaudio" value="yes"/> -->
<!-- switch parameters (required), where to send calls to -->
<param name="dialplan" value="XML"/>
<param name="context" value="default"/>
</span>
</pritap_spans>
</configuration>
+22 -6
View File
@@ -2806,7 +2806,7 @@ static ftdm_status_t ftdmchan_activate_dtmf_buffer(ftdm_channel_t *ftdmchan)
static ftdm_status_t ftdm_insert_dtmf_pause(ftdm_channel_t *ftdmchan, ftdm_size_t pausems)
{
void *data = NULL;
unsigned int datalen = pausems * sizeof(uint16_t);
ftdm_size_t datalen = pausems * sizeof(uint16_t);
data = ftdm_malloc(datalen);
ftdm_assert(data, "Failed to allocate memory\n");
@@ -3800,7 +3800,6 @@ FT_DECLARE(void) ftdm_generate_sln_silence(int16_t *data, uint32_t samples, uint
FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen)
{
ftdm_status_t status = FTDM_FAIL;
fio_codec_t codec_func = NULL;
ftdm_size_t max = *datalen;
@@ -3822,11 +3821,10 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v
}
if (codec_func) {
status = codec_func(data, max, datalen);
codec_func(data, max, datalen);
} else {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!");
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "no codec function to perform transcoding from %d to %d\n", ftdmchan->native_codec, ftdmchan->effective_codec);
status = FTDM_FAIL;
}
}
@@ -3861,7 +3859,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v
} else {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!");
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "invalid effective codec %d\n", ftdmchan->effective_codec);
status = FTDM_FAIL;
goto done;
}
}
@@ -4591,6 +4588,7 @@ static ftdm_status_t load_config(void)
ftdm_analog_start_type_t tmp;
ftdm_size_t len = 0;
ftdm_channel_config_t chan_config;
ftdm_status_t ret = FTDM_SUCCESS;
memset(&chan_config, 0, sizeof(chan_config));
sprintf(chan_config.group_name, "__default");
@@ -4627,6 +4625,13 @@ static ftdm_status_t load_config(void)
*name++ = '\0';
}
/* Verify is trunk_type was specified for previous span */
if (span && span->trunk_type == FTDM_TRUNK_NONE) {
ftdm_log(FTDM_LOG_ERROR, "trunk_type not specified for span %d (%s)\n", span->span_id, span->name);
ret = FTDM_FAIL;
goto done;
}
if (ftdm_span_create(type, name, &span) == FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_DEBUG, "created span %d (%s) of type %s\n", span->span_id, span->name, type);
d = 0;
@@ -4824,11 +4829,22 @@ static ftdm_status_t load_config(void)
ftdm_log(FTDM_LOG_ERROR, "unknown param [%s] '%s' / '%s'\n", cfg.category, var, val);
}
}
/* Verify is trunk_type was specified for the last span */
if (span && span->trunk_type == FTDM_TRUNK_NONE) {
ftdm_log(FTDM_LOG_ERROR, "trunk_type not specified for span %d (%s)\n", span->span_id, span->name);
ret = FTDM_FAIL;
}
done:
ftdm_config_close_file(&cfg);
ftdm_log(FTDM_LOG_INFO, "Configured %u channel(s)\n", configured);
if (!configured) {
ret = FTDM_FAIL;
}
return configured ? FTDM_SUCCESS : FTDM_FAIL;
return ret;
}
static ftdm_status_t process_module_config(ftdm_io_interface_t *fio)
@@ -401,7 +401,7 @@ static void analog_dial(ftdm_channel_t *ftdmchan, uint32_t *state_counter, uint3
ftdmchan->needed_tones[FTDM_TONEMAP_FAIL1] = 1;
ftdmchan->needed_tones[FTDM_TONEMAP_FAIL2] = 1;
ftdmchan->needed_tones[FTDM_TONEMAP_FAIL3] = 1;
*dial_timeout = ((ftdmchan->dtmf_on + ftdmchan->dtmf_off) * strlen(ftdmchan->caller_data.dnis.digits)) + 2000;
*dial_timeout = (uint32_t)((ftdmchan->dtmf_on + ftdmchan->dtmf_off) * strlen(ftdmchan->caller_data.dnis.digits)) + 2000;
}
}
}
@@ -932,6 +932,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
ftdm_channel_lock(closed_chan);
if (ftdmchan->type == FTDM_CHAN_TYPE_FXO && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Going onhook");
ftdm_channel_command(ftdmchan, FTDM_COMMAND_ONHOOK, NULL);
}
@@ -34,6 +34,10 @@
#include "private/ftdm_core.h"
#include "ftmod_libpri.h"
#ifndef MIN
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
#endif
static void _ftdm_channel_set_state_force(ftdm_channel_t *chan, const ftdm_channel_state_t state)
{
assert(chan);
@@ -476,7 +480,7 @@ static ftdm_state_map_t isdn_state_map = {
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_DOWN, FTDM_END},
{FTDM_CHANNEL_STATE_DIALTONE, FTDM_CHANNEL_STATE_RING, FTDM_END}
{FTDM_CHANNEL_STATE_DIALTONE, FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_END}
},
{
ZSD_INBOUND,
@@ -484,6 +488,12 @@ static ftdm_state_map_t isdn_state_map = {
{FTDM_CHANNEL_STATE_DIALTONE, FTDM_END},
{FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
},
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_COLLECT, FTDM_END},
{FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
},
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
@@ -656,6 +666,29 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
}
break;
case FTDM_CHANNEL_STATE_COLLECT: /* Overlap receive */
{
if (!ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) {
if (!call) {
ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "No call handle\n");
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
}
else if (pri_need_more_info(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0)) {
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "Failed to send INFORMATION request\n");
/* hangup call */
caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP);
}
} else {
ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "Overlap receiving on outbound call?\n");
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
}
}
break;
case FTDM_CHANNEL_STATE_RING:
{
/*
@@ -837,11 +870,57 @@ static __inline__ void check_state(ftdm_span_t *span)
*/
static int on_info(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
{
ftdm_log(FTDM_LOG_DEBUG, "number is: %s\n", pevent->ring.callednum);
ftdm_span_t *span = spri->span;
ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->ring.channel);
ftdm_caller_data_t *caller_data = NULL;
if (strlen(pevent->ring.callednum) > 3) {
ftdm_log(FTDM_LOG_DEBUG, "final number is: %s\n", pevent->ring.callednum);
pri_answer(spri->pri, pevent->ring.call, 0, 1);
if (!chan) {
ftdm_log(FTDM_LOG_CRIT, "-- Info on channel %d:%d %s but it's not in use?\n", ftdm_span_get_id(span), pevent->ring.channel);
return 0;
}
caller_data = ftdm_channel_get_caller_data(chan);
switch (ftdm_channel_get_state(chan)) {
case FTDM_CHANNEL_STATE_COLLECT: /* TE-mode overlap receiving */
ftdm_log_chan(chan, FTDM_LOG_DEBUG, "-- Incoming INFORMATION indication, current called number: '%s', number complete: %s\n",
pevent->ring.callednum, pevent->ring.complete ? "yes" : "no");
/* append digits to dnis */
if (!ftdm_strlen_zero(pevent->ring.callednum)) {
int digits = strlen(pevent->ring.callednum);
int offset = strlen(caller_data->dnis.digits);
int len = MIN(sizeof(caller_data->dnis.digits) - 1 - offset, digits); /* max. length without terminator */
if (len < digits) {
ftdm_log_chan(chan, FTDM_LOG_WARNING, "Length %d of digit string exceeds available space %d of DNIS, truncating!\n",
digits, len);
}
ftdm_copy_string(&caller_data->dnis.digits[offset], (char *)pevent->ring.callednum, len + 1); /* max. length with terminator */
caller_data->dnis.digits[offset + len] = '\0';
}
if (pevent->ring.complete) {
ftdm_log_chan_msg(chan, FTDM_LOG_DEBUG, "Number complete indicated, moving channel to RING state\n");
/* notify switch */
ftdm_set_state(chan, FTDM_CHANNEL_STATE_RING);
}
break;
case FTDM_CHANNEL_STATE_DIALTONE: /* NT-mode overlap receiving */
ftdm_log_chan(chan, FTDM_LOG_DEBUG, "-- Incoming INFORMATION indication, current called number: '%s'\n",
pevent->ring.callednum);
/* Need to add proper support for overlap receiving in NT-mode (requires FreeSWITCH + FreeTDM core support) */
if (strlen(pevent->ring.callednum) > 3) {
ftdm_log(FTDM_LOG_DEBUG, "final number is: %s\n", pevent->ring.callednum);
pri_answer(spri->pri, pevent->ring.call, 0, 1);
}
break;
default:
ftdm_log_chan(chan, FTDM_LOG_ERROR, "-- INFORMATION indication on channel %d:%d in invalid state '%s'\n",
ftdm_channel_get_span_id(chan),
ftdm_channel_get_id(chan),
ftdm_channel_get_state_str(chan));
}
return 0;
}
@@ -878,7 +957,15 @@ static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even
pri_hangup(spri->pri, pevent->hangup.call, pevent->hangup.cause);
chan->caller_data.hangup_cause = pevent->hangup.cause;
ftdm_set_state(chan, FTDM_CHANNEL_STATE_TERMINATING);
switch (ftdm_channel_get_state(chan)) {
case FTDM_CHANNEL_STATE_DIALTONE:
case FTDM_CHANNEL_STATE_COLLECT:
ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP);
break;
default:
ftdm_set_state(chan, FTDM_CHANNEL_STATE_TERMINATING);
}
break;
case LPWRAP_PRI_EVENT_HANGUP_ACK: /* */
@@ -1112,6 +1199,7 @@ out:
static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
{
ftdm_span_t *span = spri->span;
ftdm_libpri_data_t *isdn_data = span->signal_data;
ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->ring.channel);
ftdm_caller_data_t *caller_data = NULL;
int ret = 0;
@@ -1187,8 +1275,14 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
/* hurr, this is valid as along as nobody releases the call */
chan->call_data = pevent->ring.call;
ftdm_set_state(chan, FTDM_CHANNEL_STATE_RING);
/* only go to RING state if we have the complete called number (indicated via pevent->complete flag) */
if (!pevent->ring.complete && (isdn_data->overlap & FTMOD_LIBPRI_OVERLAP_RECEIVE)) {
ftdm_log(FTDM_LOG_DEBUG, "RING event without complete indicator, waiting for more digits\n");
ftdm_set_state(chan, FTDM_CHANNEL_STATE_COLLECT);
} else {
ftdm_log(FTDM_LOG_DEBUG, "RING event with complete indicator (or overlap receive disabled)\n");
ftdm_set_state(chan, FTDM_CHANNEL_STATE_RING);
}
done:
ftdm_channel_unlock(chan);
return ret;
@@ -1878,6 +1972,25 @@ static int parse_ton(const char *ton)
return PRI_UNKNOWN;
}
/**
* \brief Parse overlap string to value
* \param val String to parse
* \return Overlap flags
*/
static int parse_overlap_dial(const char *val)
{
if (!strcasecmp(val, "yes") || !strcasecmp(val, "both"))
return FTMOD_LIBPRI_OVERLAP_BOTH;
if (!strcasecmp(val, "incoming") || !strcasecmp(val, "receive"))
return FTMOD_LIBPRI_OVERLAP_RECEIVE;
if (!strcasecmp(val, "outgoing") || !strcasecmp(val, "send"))
return FTMOD_LIBPRI_OVERLAP_SEND;
if (!strcasecmp(val, "no"))
return FTMOD_LIBPRI_OVERLAP_NONE;
return -1;
}
/**
* \brief Parses an option string to flags
* \param in String to parse for configuration options
@@ -2034,6 +2147,12 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
else if (!strcasecmp(var, "l1") || !strcasecmp(var, "layer1")) {
isdn_data->layer1 = parse_layer1(val);
}
else if (!strcasecmp(var, "overlapdial")) {
if ((isdn_data->overlap = parse_overlap_dial(val)) == -1) {
ftdm_log(FTDM_LOG_ERROR, "Invalid overlap flag, ignoring parameter\n");
isdn_data->overlap = FTMOD_LIBPRI_OVERLAP_NONE;
}
}
else if (!strcasecmp(var, "debug")) {
if (parse_debug(val, &isdn_data->debug_mask) == -1) {
ftdm_log(FTDM_LOG_ERROR, "Invalid debug flag, ignoring parameter\n");
@@ -51,6 +51,12 @@ typedef enum {
FTMOD_LIBPRI_RUNNING = (1 << 0)
} ftdm_isdn_flag_t;
typedef enum {
FTMOD_LIBPRI_OVERLAP_NONE = 0,
FTMOD_LIBPRI_OVERLAP_RECEIVE = (1 << 0),
FTMOD_LIBPRI_OVERLAP_SEND = (1 << 1)
#define FTMOD_LIBPRI_OVERLAP_BOTH (FTMOD_LIBPRI_OVERLAP_RECEIVE | FTMOD_LIBPRI_OVERLAP_SEND)
} ftdm_isdn_overlap_t;
struct ftdm_libpri_data {
ftdm_channel_t *dchan;
@@ -60,6 +66,7 @@ struct ftdm_libpri_data {
int mode;
int dialect;
int overlap; /*!< Overlap dial flags */
unsigned int layer1;
unsigned int ton;
@@ -57,6 +57,7 @@ typedef struct pritap {
int32_t flags;
struct pri *pri;
int debug;
uint8_t mixaudio;
ftdm_channel_t *dchan;
ftdm_span_t *span;
ftdm_span_t *peerspan;
@@ -752,6 +753,7 @@ static ftdm_status_t ftdm_pritap_sig_read(ftdm_channel_t *ftdmchan, void *data,
ftdm_status_t status;
fio_codec_t codec_func;
ftdm_channel_t *peerchan = ftdmchan->call_data;
pritap_t *pritap = ftdmchan->span->signal_data;
int16_t chanbuf[size];
int16_t peerbuf[size];
int16_t mixedbuf[size];
@@ -762,6 +764,11 @@ static ftdm_status_t ftdm_pritap_sig_read(ftdm_channel_t *ftdmchan, void *data,
return FTDM_SUCCESS;
}
if (!pritap->mixaudio) {
/* No mixing requested */
return FTDM_SUCCESS;
}
if (ftdmchan->native_codec != peerchan->native_codec) {
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Invalid peer channel with format %d, ours = %d\n",
peerchan->native_codec, ftdmchan->native_codec);
@@ -829,6 +836,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_pritap_configure_span)
uint32_t i;
const char *var, *val;
const char *debug = NULL;
uint8_t mixaudio = 1;
ftdm_channel_t *dchan = NULL;
pritap_t *pritap = NULL;
ftdm_span_t *peerspan = NULL;
@@ -857,6 +865,8 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_pritap_configure_span)
if (!strcasecmp(var, "debug")) {
debug = val;
} else if (!strcasecmp(var, "mixaudio")) {
mixaudio = ftdm_true(val);
} else if (!strcasecmp(var, "peerspan")) {
if (ftdm_span_find_by_name(val, &peerspan) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Invalid tapping peer span %s\n", val);
@@ -880,6 +890,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_pritap_configure_span)
pritap->debug = parse_debug(debug);
pritap->dchan = dchan;
pritap->peerspan = peerspan;
pritap->mixaudio = mixaudio;
span->start = ftdm_pritap_start;
span->stop = ftdm_pritap_stop;
@@ -344,7 +344,6 @@ static void *ftdm_sangoma_isdn_io_run(ftdm_thread_t *me, void *obj)
uint8_t data[1000];
unsigned i = 0;
ftdm_status_t status = FTDM_SUCCESS;
ftdm_wait_flag_t wflags = FTDM_READ;
ftdm_span_t *span = (ftdm_span_t*) obj;
ftdm_size_t len = 0;
ftdm_channel_t *ftdmchan = NULL;
@@ -356,10 +355,6 @@ static void *ftdm_sangoma_isdn_io_run(ftdm_thread_t *me, void *obj)
/* Initialize the d-channel */
ftdm_assert(((sngisdn_span_data_t*)span->signal_data)->dchan, "Span does not have a dchannel");
ftdm_channel_set_feature(((sngisdn_span_data_t*)span->signal_data)->dchan, FTDM_CHANNEL_FEATURE_IO_STATS);
ftdm_sangoma_isdn_dchan_set_queue_size(((sngisdn_span_data_t*)span->signal_data)->dchan);
ftdm_channel_open_chan(((sngisdn_span_data_t*)span->signal_data)->dchan);
chaniter = ftdm_span_get_chan_iterator(span, NULL);
if (!chaniter) {
ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
@@ -369,7 +364,6 @@ static void *ftdm_sangoma_isdn_io_run(ftdm_thread_t *me, void *obj)
while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) {
len = 1000;
waitms = 1000;
wflags = FTDM_READ;
memset(poll_events, 0, sizeof(short)*span->chan_count);
poll_events[i] |= FTDM_EVENTS;
@@ -1039,7 +1033,13 @@ static ftdm_status_t ftdm_sangoma_isdn_dtmf(ftdm_channel_t *ftdmchan, const char
static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
{
sngisdn_span_data_t *signal_data = span->signal_data;
ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id);
ftdm_channel_set_feature(((sngisdn_span_data_t*)span->signal_data)->dchan, FTDM_CHANNEL_FEATURE_IO_STATS);
ftdm_channel_open_chan(((sngisdn_span_data_t*)span->signal_data)->dchan);
ftdm_sangoma_isdn_dchan_set_queue_size(((sngisdn_span_data_t*)span->signal_data)->dchan);
if (sngisdn_stack_start(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name);
return FTDM_FAIL;
@@ -1073,6 +1073,11 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
return FTDM_FAIL;
}
if (signal_data->restart_timeout) {
ftdm_log(FTDM_LOG_DEBUG, "%s:Scheduling Restart timeout\n", signal_data->ftdm_span->name);
ftdm_sched_timer(signal_data->sched, "restart_timeout", signal_data->restart_timeout,
sngisdn_restart_timeout, (void*) signal_data, &signal_data->timers[SNGISDN_SPAN_TIMER_RESTART]);
}
ftdm_log(FTDM_LOG_DEBUG,"Finished starting span %s\n", span->name);
return FTDM_SUCCESS;
}
@@ -154,12 +154,18 @@ typedef struct ftdm_sngisdn_prog_ind {
} ftdm_sngisdn_progind_t;
/* Only timers that can be cancelled are listed here */
#define SNGISDN_NUM_TIMERS 2
/* Increase NUM_TIMERS as number of ftdm_sngisdn_timer_t increases */
typedef enum {
SNGISDN_TIMER_FACILITY = 0,
SNGISDN_TIMER_ATT_TRANSFER,
} ftdm_sngisdn_timer_t;
#define SNGISDN_NUM_CHAN_TIMERS 2
/* Increase SNGISDN_NUM_CHAN_TIMERS as number of ftdm_sngisdn_chan_timer_t increases */
typedef enum {
SNGISDN_CHAN_TIMER_FACILITY,
SNGISDN_CHAN_TIMER_ATT_TRANSFER,
} ftdm_sngisdn_chan_timer_t;
#define SNGISDN_NUM_SPAN_TIMERS 1
/* Increase SNGISDN_NUM_SPAN_TIMERS as number of ftdm_sngisdn_spanan_timer_t increases */
typedef enum {
SNGISDN_SPAN_TIMER_RESTART,
} ftdm_sngisdn_span_timer_t;
typedef struct sngisdn_glare_data {
int16_t suId;
@@ -210,7 +216,7 @@ typedef struct sngisdn_chan_data {
uint8_t globalFlg;
sngisdn_glare_data_t glare;
ftdm_timer_id_t timers[SNGISDN_NUM_TIMERS];
ftdm_timer_id_t timers[SNGISDN_NUM_CHAN_TIMERS];
sngisdn_transfer_data_t transfer_data;
/* variables saved here will be sent to the user application
@@ -252,8 +258,10 @@ typedef struct sngisdn_span_data {
uint8_t raw_trace_q921; /* TODO: combine with trace_flags */
uint8_t timer_t3;
uint8_t restart_opt;
uint8_t restart_timeout;
uint8_t force_sending_complete;
char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
ftdm_timer_id_t timers[SNGISDN_NUM_SPAN_TIMERS];
ftdm_sched_t *sched;
ftdm_queue_t *event_queue;
} sngisdn_span_data_t;
@@ -452,8 +460,7 @@ ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb);
ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb);
ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *display);
ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr);
ftdm_status_t get_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt);
ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd);
ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
@@ -514,6 +521,7 @@ void sngisdn_delayed_connect(void* p_sngisdn_info);
void sngisdn_delayed_disconnect(void* p_sngisdn_info);
void sngisdn_facility_timeout(void* p_sngisdn_info);
void sngisdn_t3_timeout(void* p_sngisdn_info);
void sngisdn_restart_timeout(void* p_signal_data);
/* Stack management functions */
ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span);
@@ -359,6 +359,8 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
ftdm_set_bearer_layer1(val, (uint8_t*)&span->default_caller_data.bearer_layer1);
} else if (!strcasecmp(var, "channel-restart-on-link-up")) {
parse_yesno(var, val, &signal_data->restart_opt);
} else if (!strcasecmp(var, "channel-restart-timeout")) {
signal_data->restart_timeout = atoi(val);
} else if (!strcasecmp(var, "local-number")) {
if (add_local_number(val, span) != FTDM_SUCCESS) {
return FTDM_FAIL;
@@ -422,7 +422,7 @@ ftdm_status_t sngisdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management
cfg.t.cfg.s.bdDLSAP.n200 = 3; /* n200 */
cfg.t.cfg.s.bdDLSAP.congTmr = 300; /* congestion timer */
cfg.t.cfg.s.bdDLSAP.t200Tmr = 1; /* t1 changed from 25 */
cfg.t.cfg.s.bdDLSAP.t200Tmr = 3; /* t1 changed from 25 */
cfg.t.cfg.s.bdDLSAP.t203Tmr = 10; /* t3 changed from 50 */
cfg.t.cfg.s.bdDLSAP.mod = 128; /* modulo */
cfg.t.cfg.s.bdDLSAP.selector = 0; /* Selector 0 */
@@ -681,12 +681,7 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.clrGlr = FALSE; /* in case of glare, do not clear local call */
cfg.t.cfg.s.inDLSAP.statEnqOpt = TRUE;
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN ||
signal_data->switchtype == SNGISDN_SWITCH_INSNET) {
cfg.t.cfg.s.inDLSAP.rstOpt = FALSE;
} else {
cfg.t.cfg.s.inDLSAP.rstOpt = TRUE;
}
cfg.t.cfg.s.inDLSAP.rstOpt = TRUE;
} else {
cfg.t.cfg.s.inDLSAP.ackOpt = FALSE;
cfg.t.cfg.s.inDLSAP.intType = USER;
@@ -803,8 +798,10 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.tmr.t322.val = 4;
cfg.t.cfg.s.inDLSAP.tmr.t332.enb = FALSE;
cfg.t.cfg.s.inDLSAP.tmr.t332.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.tRst.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.tRst.val = 8;
cfg.t.cfg.s.inDLSAP.tmr.tAns.enb = FALSE; /* non-standard timer */
cfg.t.cfg.s.inDLSAP.tmr.t396.enb = FALSE; /* non-standard timer */
cfg.t.cfg.s.inDLSAP.tmr.t397.enb = TRUE; /* non-standard timer */
@@ -34,8 +34,7 @@
#include "ftmod_sangoma_isdn.h"
static ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn);
static void sngisdn_process_restart_confirm(ftdm_channel_t *ftdmchan);
static ftdm_status_t sngisdn_force_down(ftdm_channel_t *ftdmchan);
static ftdm_status_t sngisdn_bring_down(ftdm_channel_t *ftdmchan);
/* Remote side transmit a SETUP */
void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
@@ -135,11 +134,8 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
get_calling_subaddr(ftdmchan, &conEvnt->cgPtySad);
get_prog_ind_ie(ftdmchan, &conEvnt->progInd);
get_facility_ie(ftdmchan, &conEvnt->facilityStr);
get_calling_name(ftdmchan, conEvnt);
if (get_calling_name_from_display(ftdmchan, &conEvnt->display) != FTDM_SUCCESS) {
get_calling_name_from_usr_usr(ftdmchan, &conEvnt->usrUsr);
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Incoming call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits);
if (conEvnt->bearCap[0].eh.pres) {
@@ -185,7 +181,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
/* Launch timer in case we never get a FACILITY msg */
if (signal_data->facility_timeout) {
ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout,
sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_CHAN_TIMER_FACILITY]);
}
break;
} else if (ret_val == 0) {
@@ -836,7 +832,7 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
}
if (signal_data->facility_timeout) {
/* Cancel facility timeout */
ftdm_sched_cancel_timer(signal_data->sched, sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
ftdm_sched_cancel_timer(signal_data->sched, sngisdn_info->timers[SNGISDN_CHAN_TIMER_FACILITY]);
}
}
@@ -927,7 +923,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
switch(call_state) {
/* Sere ITU-T Q931 for definition of call states */
case 0: /* Remote switch thinks there are no calls on this channel */
if (sngisdn_force_down(ftdmchan) != FTDM_SUCCESS) {
if (sngisdn_bring_down(ftdmchan) != FTDM_SUCCESS) {
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
}
break;
@@ -1121,29 +1117,12 @@ void sngisdn_process_srv_cfm (sngisdn_event_data_t *sngisdn_event)
return;
}
static void sngisdn_process_restart_confirm(ftdm_channel_t *ftdmchan)
{
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_RESET:
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
break;
case FTDM_CHANNEL_STATE_DOWN:
/* Do nothing */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RESTART CFM in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
}
return;
}
static ftdm_status_t sngisdn_force_down(ftdm_channel_t *ftdmchan)
static ftdm_status_t sngisdn_bring_down(ftdm_channel_t *ftdmchan)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
ftdm_status_t status = FTDM_SUCCESS;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Forcing channel to DOWN state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Bringing channel to DOWN state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_DOWN:
/* Do nothing */
@@ -1196,38 +1175,36 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
return;
}
if (rstEvnt->rstInd.eh.pres != PRSNT_NODEF && rstEvnt->rstInd.rstClass.pres != PRSNT_NODEF) {
ftdm_log(FTDM_LOG_DEBUG, "Received RESTART, but Restart Indicator IE not present\n");
return;
}
switch(rstEvnt->rstInd.rstClass.val) {
case IN_CL_INDCHAN: /* Indicated b-channel */
if (rstEvnt->chanId.eh.pres) {
if (rstEvnt->chanId.intType.val == IN_IT_BASIC) {
if (rstEvnt->chanId.infoChanSel.pres == PRSNT_NODEF) {
chan_no = rstEvnt->chanId.infoChanSel.val;
}
} else if (rstEvnt->chanId.intType.val == IN_IT_OTHER) {
if (rstEvnt->chanId.chanNmbSlotMap.pres == PRSNT_NODEF) {
chan_no = rstEvnt->chanId.chanNmbSlotMap.val[0];
if (rstEvnt->rstInd.eh.pres == PRSNT_NODEF && rstEvnt->rstInd.rstClass.pres == PRSNT_NODEF) {
switch(rstEvnt->rstInd.rstClass.val) {
case IN_CL_INDCHAN: /* Indicated b-channel */
if (rstEvnt->chanId.eh.pres) {
if (rstEvnt->chanId.intType.val == IN_IT_BASIC) {
if (rstEvnt->chanId.infoChanSel.pres == PRSNT_NODEF) {
chan_no = rstEvnt->chanId.infoChanSel.val;
}
} else if (rstEvnt->chanId.intType.val == IN_IT_OTHER) {
if (rstEvnt->chanId.chanNmbSlotMap.pres == PRSNT_NODEF) {
chan_no = rstEvnt->chanId.chanNmbSlotMap.val[0];
}
}
}
}
if (!chan_no) {
ftdm_log(FTDM_LOG_CRIT, "Failed to determine channel from RESTART\n");
if (!chan_no) {
ftdm_log(FTDM_LOG_CRIT, "Failed to determine channel from RESTART\n");
return;
}
break;
case IN_CL_SNGINT: /* Single interface */
case IN_CL_ALLINT: /* All interfaces */
/* In case restart class indicates all interfaces, we will duplicate
this event on each span associated to this d-channel in sngisdn_rcv_rst_cfm,
so treat it as a single interface anyway */
chan_no = 0;
break;
default:
ftdm_log(FTDM_LOG_CRIT, "Invalid restart indicator class:%d\n", rstEvnt->rstInd.rstClass.val);
return;
}
break;
case IN_CL_SNGINT: /* Single interface */
case IN_CL_ALLINT: /* All interfaces */
/* In case restart class indicates all interfaces, we will duplicate
this event on each span associated to this d-channel in sngisdn_rcv_rst_cfm,
so treat it as a single interface anyway */
break;
default:
ftdm_log(FTDM_LOG_CRIT, "Invalid restart indicator class:%d\n", rstEvnt->rstInd.rstClass.val);
return;
}
}
if (chan_no) { /* For a single channel */
@@ -1235,7 +1212,7 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
ftdm_log(FTDM_LOG_CRIT, "Received RESTART on invalid channel:%d\n", chan_no);
} else {
ftdm_channel_t *ftdmchan = ftdm_span_get_channel(signal_data->ftdm_span, chan_no);
sngisdn_process_restart_confirm(ftdmchan);
sngisdn_bring_down(ftdmchan);
}
} else { /* for all channels */
ftdm_iterator_t *chaniter = NULL;
@@ -1243,7 +1220,7 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
sngisdn_process_restart_confirm((ftdm_channel_t*)ftdm_iterator_current(curr));
sngisdn_bring_down((ftdm_channel_t*)ftdm_iterator_current(curr));
}
ftdm_iterator_free(chaniter);
}
@@ -1272,10 +1249,6 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
/* TODO: readjust this when NFAS is implemented as signal_data will not always be the first
* span for that d-channel */
if (!rstEvnt->rstInd.eh.pres || !rstEvnt->rstInd.rstClass.pres) {
ftdm_log(FTDM_LOG_DEBUG, "Received RESTART IND, but Restart Indicator IE not present\n");
return;
}
signal_data = g_sngisdn_data.dchans[dChan].spans[1];
@@ -1283,46 +1256,48 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_log(FTDM_LOG_CRIT, "Received RESTART IND on unconfigured span (suId:%d)\n", suId);
return;
}
if (signal_data->restart_timeout) {
ftdm_sched_cancel_timer(signal_data->sched, signal_data->timers[SNGISDN_SPAN_TIMER_RESTART]);
}
ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART IND (suId:%u dChan:%d ces:%d %s)\n", suId, dChan, ces,
ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART IND (suId:%u dChan:%d ces:%d %s(%d))\n", suId, dChan, ces,
(evntType == IN_LNK_DWN)?"LNK_DOWN":
(evntType == IN_LNK_UP)?"LNK_UP":
(evntType == IN_INDCHAN)?"b-channel":
(evntType == IN_LNK_DWN_DM_RLS)?"NFAS service procedures":
(evntType == IN_SWCHD_BU_DCHAN)?"NFAS switchover to backup":"Unknown");
(evntType == IN_SWCHD_BU_DCHAN)?"NFAS switchover to backup":"Unknown", evntType);
if (!rstEvnt->rstInd.eh.pres || !rstEvnt->rstInd.rstClass.pres) {
ftdm_log(FTDM_LOG_DEBUG, "Received RESTART IND, but Restart Indicator IE not present\n");
return;
}
switch(rstEvnt->rstInd.rstClass.val) {
case IN_CL_INDCHAN: /* Indicated b-channel */
if (rstEvnt->chanId.eh.pres) {
if (rstEvnt->chanId.intType.val == IN_IT_BASIC) {
if (rstEvnt->chanId.infoChanSel.pres == PRSNT_NODEF) {
chan_no = rstEvnt->chanId.infoChanSel.val;
}
} else if (rstEvnt->chanId.intType.val == IN_IT_OTHER) {
if (rstEvnt->chanId.chanNmbSlotMap.pres == PRSNT_NODEF) {
chan_no = rstEvnt->chanId.chanNmbSlotMap.val[0];
if (rstEvnt->rstInd.eh.pres == PRSNT_NODEF && rstEvnt->rstInd.rstClass.pres == PRSNT_NODEF) {
switch(rstEvnt->rstInd.rstClass.val) {
case IN_CL_INDCHAN: /* Indicated b-channel */
if (rstEvnt->chanId.eh.pres) {
if (rstEvnt->chanId.intType.val == IN_IT_BASIC) {
if (rstEvnt->chanId.infoChanSel.pres == PRSNT_NODEF) {
chan_no = rstEvnt->chanId.infoChanSel.val;
}
} else if (rstEvnt->chanId.intType.val == IN_IT_OTHER) {
if (rstEvnt->chanId.chanNmbSlotMap.pres == PRSNT_NODEF) {
chan_no = rstEvnt->chanId.chanNmbSlotMap.val[0];
}
}
}
}
if (!chan_no) {
ftdm_log(FTDM_LOG_CRIT, "Failed to determine channel from RESTART\n");
if (!chan_no) {
ftdm_log(FTDM_LOG_CRIT, "Failed to determine channel from RESTART\n");
return;
}
break;
case IN_CL_SNGINT: /* Single interface */
case IN_CL_ALLINT: /* All interfaces */
/* In case restart class indicates all interfaces, we will duplicate
this event on each span associated to this d-channel in sngisdn_rcv_rst_cfm,
so treat it as a single interface anyway */
chan_no = 0;
break;
default:
ftdm_log(FTDM_LOG_CRIT, "Invalid restart indicator class:%d\n", rstEvnt->rstInd.rstClass.val);
return;
}
break;
case IN_CL_SNGINT: /* Single interface */
case IN_CL_ALLINT: /* All interfaces */
/* In case restart class indicates all interfaces, we will duplicate
this event on each span associated to this d-channel in sngisdn_rcv_rst_cfm,
so treat it as a single interface anyway */
break;
default:
ftdm_log(FTDM_LOG_CRIT, "Invalid restart indicator class:%d\n", rstEvnt->rstInd.rstClass.val);
return;
}
}
if (chan_no) { /* For a single channel */
@@ -1336,7 +1311,7 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
if (ftdmchan->physical_chan_id == chan_no) {
sngisdn_force_down(ftdmchan);
sngisdn_bring_down(ftdmchan);
}
}
ftdm_iterator_free(chaniter);
@@ -1347,7 +1322,7 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
sngisdn_force_down((ftdm_channel_t*)ftdm_iterator_current(curr));
sngisdn_bring_down((ftdm_channel_t*)ftdm_iterator_current(curr));
}
ftdm_iterator_free(chaniter);
}
@@ -491,7 +491,18 @@ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len)
/* Should we trigger congestion here? */
l1_frame.flags |= SNG_L1FRAME_QUEUE_FULL;
}
#if 0
if (1) {
int i;
char string [2000];
unsigned string_len = 0;
for (i = 0; i < l1_frame.len; i++) {
string_len += sprintf(&string[string_len], "0x%02x ", l1_frame.data[i]);
}
ftdm_log_chan(dchan, FTDM_LOG_CRIT, "\nL1 RX [%s] flags:%x\n", string, l1_frame.flags);
}
#endif
sng_isdn_data_ind(signal_data->dchan_id, &l1_frame);
}
@@ -903,6 +903,17 @@ int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame)
if ((flags & FTDM_WRITE)) {
#if 0
int i;
char string [2000];
unsigned string_len = 0;
for (i = 0; i < length; i++) {
string_len += sprintf(&string[string_len], "0x%02x ", l1_frame->data[i]);
}
ftdm_log_chan(signal_data->dchan, FTDM_LOG_CRIT, "\nL1 TX [%s]\n", string);
#endif
status = signal_data->dchan->fio->write(signal_data->dchan, l1_frame->data, (ftdm_size_t*)&length);
if (status != FTDM_SUCCESS) {
ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_CRIT, "Failed to transmit frame\n");
@@ -45,6 +45,9 @@ SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str
static uint8_t get_trillium_val(ftdm2trillium_t *vals, uint8_t ftdm_val, uint8_t default_val);
static uint8_t get_ftdm_val(ftdm2trillium_t *vals, uint8_t trillium_val, uint8_t default_val);
ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr);
ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *display);
ftdm_status_t get_calling_name_from_ntDisplay(ftdm_channel_t *ftdmchan, NtDisplay *display);
extern ftdm_sngisdn_data_t g_sngisdn_data;
@@ -355,6 +358,20 @@ ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *d
return FTDM_SUCCESS;
}
ftdm_status_t get_calling_name_from_ntDisplay(ftdm_channel_t *ftdmchan, NtDisplay *display)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (display->eh.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
if (display->dispInfo.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
ftdm_copy_string(caller_data->cid_name, (const char*)display->dispInfo.val, display->dispInfo.len+1);
return FTDM_SUCCESS;
}
ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
@@ -374,6 +391,24 @@ ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *us
return FTDM_SUCCESS;
}
ftdm_status_t get_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt)
{
ftdm_status_t status = FTDM_FAIL;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
if (signal_data->switchtype == SNGISDN_SWITCH_DMS100) {
status = get_calling_name_from_ntDisplay(ftdmchan, &conEvnt->ntDisplay[0]);
} else {
status = get_calling_name_from_display(ftdmchan, &conEvnt->display);
}
if (status != FTDM_SUCCESS) {
status = get_calling_name_from_usr_usr(ftdmchan, &conEvnt->usrUsr);
}
return status;
}
ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
{
char subaddress[100];
@@ -694,12 +729,22 @@ ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt)
/* follow through */
case SNGISDN_SWITCH_5ESS:
case SNGISDN_SWITCH_4ESS:
case SNGISDN_SWITCH_DMS100:
conEvnt->display.eh.pres = PRSNT_NODEF;
conEvnt->display.dispInfo.pres = PRSNT_NODEF;
conEvnt->display.dispInfo.len = len;
memcpy(conEvnt->display.dispInfo.val, caller_data->cid_name, len);
break;
case SNGISDN_SWITCH_DMS100:
conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF;
conEvnt->ntDisplay[0].dispTypeNt.pres = PRSNT_NODEF;
conEvnt->ntDisplay[0].dispTypeNt.val = 0x01; /* Calling Party Name */
conEvnt->ntDisplay[0].assocInfo.pres = PRSNT_NODEF;
conEvnt->ntDisplay[0].assocInfo.val = 0x03; /* Included */
conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF;
conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF;
conEvnt->ntDisplay[0].dispInfo.pres = PRSNT_NODEF;
conEvnt->ntDisplay[0].dispInfo.len = len;
memcpy(conEvnt->ntDisplay[0].dispInfo.val, caller_data->cid_name, len);
break;
case SNGISDN_SWITCH_QSIG:
/* It seems like QSIG does not support Caller ID Name */
break;
@@ -976,7 +1021,7 @@ ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd)
return FTDM_SUCCESS;
}
void sngisdn_t3_timeout(void* p_sngisdn_info)
void sngisdn_t3_timeout(void *p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
@@ -998,7 +1043,31 @@ void sngisdn_t3_timeout(void* p_sngisdn_info)
ftdm_mutex_unlock(ftdmchan->mutex);
}
void sngisdn_delayed_setup(void* p_sngisdn_info)
void sngisdn_restart_timeout(void *p_signal_data)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t *)p_signal_data;
ftdm_span_t *span = signal_data->ftdm_span;
ftdm_log(FTDM_LOG_DEBUG, "s%d:Did not receive a RESTART from remote switch in %d ms - restarting\n", span->name, signal_data->restart_timeout);
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
ftdm_mutex_lock(ftdmchan->mutex);
if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESET);
}
ftdm_mutex_unlock(ftdmchan->mutex);
}
}
return;
}
void sngisdn_delayed_setup(void *p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
@@ -1009,7 +1078,7 @@ void sngisdn_delayed_setup(void* p_sngisdn_info)
return;
}
void sngisdn_delayed_release(void* p_sngisdn_info)
void sngisdn_delayed_release(void *p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
@@ -1032,7 +1101,7 @@ void sngisdn_delayed_release(void* p_sngisdn_info)
return;
}
void sngisdn_delayed_connect(void* p_sngisdn_info)
void sngisdn_delayed_connect(void *p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
@@ -1047,7 +1116,7 @@ void sngisdn_delayed_connect(void* p_sngisdn_info)
return;
}
void sngisdn_delayed_disconnect(void* p_sngisdn_info)
void sngisdn_delayed_disconnect(void *p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
@@ -1069,7 +1138,7 @@ void sngisdn_delayed_disconnect(void* p_sngisdn_info)
return;
}
void sngisdn_facility_timeout(void* p_sngisdn_info)
void sngisdn_facility_timeout(void *p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
@@ -114,7 +114,7 @@ void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace
{
char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
sngisdn_decode_q921(data_str, data, data_len);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN Q921] %s FRAME %s:\n%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
ftdm_safe_free(data_str);
}
@@ -144,7 +144,7 @@ void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t d
void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len)
{
int str_len;
uint32_t str_len;
uint32_t i;
uint8_t sapi, cr, ea, tei, ns, nr, pf, p, cmd;
uint8_t frame_format = 0;
@@ -211,6 +211,8 @@ void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len)
break;
}
}
print_hex_dump(str, &str_len, (uint8_t*) data, 0, data_len);
return;
}
@@ -219,7 +221,7 @@ void sngisdn_trace_interpreted_q931(sngisdn_span_data_t *signal_data, ftdm_trace
{
char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
sngisdn_decode_q931(data_str, data, data_len);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] %s FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN Q931] %s FRAME %s:\n%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
ftdm_safe_free(data_str);
}
@@ -584,11 +586,20 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
break;
case PROT_Q931_IE_DISPLAY:
{
uint8_t displayStrOct=2, j;
uint8_t j;
char displayStr[82];
uint8_t displayNtEnabled = 0;
uint8_t displayStrOct = 2;
uint8_t displayType = 0;
uint8_t assocInfo = 0;
memset(displayStr, 0, sizeof(displayStr));
if(get_bits(OCTET(3),8,8)) {
displayType = get_bits(OCTET(3),1,4);
assocInfo = get_bits(OCTET(3),5,7);
displayNtEnabled = 1;
displayStrOct++;
}
j = 0;
@@ -599,8 +610,15 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
displayStr[j++]=ia5[get_bits(OCTET(displayStrOct),1,4)][get_bits(OCTET(displayStrOct),5,8)];
}
displayStr[j]='\0';
*str_len+= sprintf(&str[*str_len], "%s(l:%d)\n",
displayStr, len);
if (displayNtEnabled) {
*str_len+= sprintf(&str[*str_len], "%s(l:%d) type:%s(%d) info:%s(%d)\n",
displayStr, len,
get_code_2_str(displayType, dcodQ931DisplayTypeTable), displayType,
get_code_2_str(assocInfo, dcodQ931AssocInfoTable), assocInfo);
} else {
*str_len+= sprintf(&str[*str_len], "%s(l:%d)\n",
displayStr, len);
}
}
break;
case PROT_Q931_IE_RESTART_IND:
@@ -578,5 +578,17 @@ struct code2str dcodQ931TypeOfSubaddressTable[] = {
{ -1, "Invalid"},
};
#endif /* __FTMOD_SANGOMA_ISDN_TRACE_H__ */
struct code2str dcodQ931DisplayTypeTable[] = {
{ 0x00, "Calling Party Name"},
{ 0x01, "Connected Party Name"},
{ 0x05, "Original Called Party Name"},
{ -1, "Invalid"},
};
struct code2str dcodQ931AssocInfoTable[] = {
{ 0x00, "Requested"},
{ 0x03, "Included"},
{ -1, "Invalid"},
};
#endif /* __FTMOD_SANGOMA_ISDN_TRACE_H__ */
@@ -164,7 +164,7 @@ static ftdm_status_t att_courtesy_vru(ftdm_channel_t *ftdmchan, sngisdn_transfer
sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_UP);
}
if (signal_data->transfer_timeout) {
ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "courtesy_transfer_timeout", signal_data->transfer_timeout, att_courtesy_transfer_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_ATT_TRANSFER]);
ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "courtesy_transfer_timeout", signal_data->transfer_timeout, att_courtesy_transfer_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_CHAN_TIMER_ATT_TRANSFER]);
}
status = FTDM_SUCCESS;
@@ -260,7 +260,7 @@ ftdm_status_t sngisdn_att_transfer_process_dtmf(ftdm_channel_t *ftdmchan, const
sngisdn_info->transfer_data.response = FTDM_TRANSFER_RESPONSE_INVALID;
}
if (signal_data->transfer_timeout) {
ftdm_sched_cancel_timer(signal_data->sched, sngisdn_info->timers[SNGISDN_TIMER_ATT_TRANSFER]);
ftdm_sched_cancel_timer(signal_data->sched, sngisdn_info->timers[SNGISDN_CHAN_TIMER_ATT_TRANSFER]);
}
if (sngisdn_info->transfer_data.response == FTDM_TRANSFER_RESPONSE_OK &&
@@ -29,6 +29,11 @@
* LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
*
* Ricardo Barroetaveña <rbarroetavena@anura.com.ar>
*
*/
/* INCLUDE ********************************************************************/
@@ -950,31 +950,31 @@ if (ftdmchan->state == new_state) { \
#define SS7_FUNC_TRACE_EXIT(a) if (g_ftdm_sngss7_data.function_trace) { \
switch (g_ftdm_sngss7_data.function_trace_level) { \
case 0: \
ftdm_log(FTDM_LOG_EMERG,"Exitting %s\n", a); \
ftdm_log(FTDM_LOG_EMERG,"Exiting %s\n", a); \
break; \
case 1: \
ftdm_log(FTDM_LOG_ALERT,"Exitting %s\n", a); \
ftdm_log(FTDM_LOG_ALERT,"Exiting %s\n", a); \
break; \
case 2: \
ftdm_log(FTDM_LOG_CRIT,"Exitting %s\n", a); \
ftdm_log(FTDM_LOG_CRIT,"Exiting %s\n", a); \
break; \
case 3: \
ftdm_log(FTDM_LOG_ERROR,"Exitting %s\n", a); \
ftdm_log(FTDM_LOG_ERROR,"Exiting %s\n", a); \
break; \
case 4: \
ftdm_log(FTDM_LOG_WARNING,"Exitting %s\n", a); \
ftdm_log(FTDM_LOG_WARNING,"Exiting %s\n", a); \
break; \
case 5: \
ftdm_log(FTDM_LOG_NOTICE,"Exitting %s\n", a); \
ftdm_log(FTDM_LOG_NOTICE,"Exiting %s\n", a); \
break; \
case 6: \
ftdm_log(FTDM_LOG_INFO,"Exitting %s\n", a); \
ftdm_log(FTDM_LOG_INFO,"Exiting %s\n", a); \
break; \
case 7: \
ftdm_log(FTDM_LOG_DEBUG,"Exitting %s\n", a); \
ftdm_log(FTDM_LOG_DEBUG,"Exiting %s\n", a); \
break; \
default: \
ftdm_log(FTDM_LOG_INFO,"Exitting %s\n", a); \
ftdm_log(FTDM_LOG_INFO,"Exiting %s\n", a); \
break; \
} /* switch (g_ftdm_sngss7_data.function_trace_level) */ \
} /* if(g_ftdm_sngss7_data.function_trace) */
+6 -6
View File
@@ -725,7 +725,7 @@ static FIO_COMMAND_FUNCTION(zt_command)
{
int command = ZT_OFFHOOK;
if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "OFFHOOK Failed");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "OFFHOOK Failed");
return FTDM_FAIL;
}
ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK);
@@ -735,7 +735,7 @@ static FIO_COMMAND_FUNCTION(zt_command)
{
int command = ZT_ONHOOK;
if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "ONHOOK Failed");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "ONHOOK Failed");
return FTDM_FAIL;
}
ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK);
@@ -745,7 +745,7 @@ static FIO_COMMAND_FUNCTION(zt_command)
{
int command = ZT_FLASH;
if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "FLASH Failed");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "FLASH Failed");
return FTDM_FAIL;
}
}
@@ -754,7 +754,7 @@ static FIO_COMMAND_FUNCTION(zt_command)
{
int command = ZT_WINK;
if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "WINK Failed");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "WINK Failed");
return FTDM_FAIL;
}
}
@@ -763,7 +763,7 @@ static FIO_COMMAND_FUNCTION(zt_command)
{
int command = ZT_RING;
if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Ring Failed");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "RING Failed");
return FTDM_FAIL;
}
ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_RINGING);
@@ -773,7 +773,7 @@ static FIO_COMMAND_FUNCTION(zt_command)
{
int command = ZT_RINGOFF;
if (ioctl(ftdmchan->sockfd, codes.HOOK, &command)) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Ring-off failed");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Ring-off Failed");
return FTDM_FAIL;
}
ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_RINGING);
+2 -2
View File
@@ -48,7 +48,7 @@
#define FTDM_MAX_CHANNELS_PHYSICAL_SPAN 32
/*! \brief Max number of physical spans per logical span */
#define FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN 32
#define FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN 128
/*! \brief Max number of channels a logical span can contain */
#define FTDM_MAX_CHANNELS_SPAN FTDM_MAX_CHANNELS_PHYSICAL_SPAN * FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN
@@ -57,7 +57,7 @@
#define FTDM_MAX_SPANS_INTERFACE 128
/*! \brief Max number of channels per hunting group */
#define FTDM_MAX_CHANNELS_GROUP 1024
#define FTDM_MAX_CHANNELS_GROUP 2048
/*! \brief Max number of groups */
#define FTDM_MAX_GROUPS_INTERFACE FTDM_MAX_SPANS_INTERFACE