Merge branch 'smgmaster' into releases.3.4.experimental_head

Conflicts:
	libs/freetdm/mod_freetdm/mod_freetdm.c
	libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
	libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
	libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
	libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c
	src/mod/endpoints/mod_sofia/mod_sofia.c
	src/mod/endpoints/mod_sofia/sofia_glue.c
This commit is contained in:
Moises Silva committed 2011-12-17 17:42:34 -05:00
commit 7bd2d154d6
615 files changed
+41286 -47127

No files matched your search

@@ -39,7 +39,8 @@ typedef enum {
FTDM_ANALOG_RUNNING = (1 << 0),
FTDM_ANALOG_CALLERID = (1 << 1),
FTDM_ANALOG_ANSWER_POLARITY_REVERSE = (1 << 2),
FTDM_ANALOG_HANGUP_POLARITY_REVERSE = (1 << 3)
FTDM_ANALOG_HANGUP_POLARITY_REVERSE = (1 << 3),
FTDM_ANALOG_POLARITY_CALLERID = (1 << 4)
} ftdm_analog_flag_t;
#define FTDM_MAX_HOTLINE_STR 20
@@ -275,6 +275,15 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
break;
}
hotline = val;
} else if (!strcasecmp(var, "polarity_callerid")) {
if (!(val = va_arg(ap, char *))) {
break;
}
if (ftdm_true(val)) {
flags |= FTDM_ANALOG_POLARITY_CALLERID;
} else {
flags &= ~FTDM_ANALOG_POLARITY_CALLERID;
}
} else {
ftdm_log(FTDM_LOG_ERROR, "Unknown parameter %s in span %s\n", var, span->name);
}
@@ -1130,8 +1139,18 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
break;
}
if (event->channel->state == FTDM_CHANNEL_STATE_DOWN) {
ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG,
"Ignoring polarity reversal because this channel is down\n");
if (ftdm_test_flag(analog_data, FTDM_ANALOG_CALLERID)
&& ftdm_test_flag(analog_data, FTDM_ANALOG_POLARITY_CALLERID)) {
ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG, "Polarity reversal detected while down, getting caller id now\n");
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID);
event->channel->ring_count = 1;
ftdm_mutex_unlock(event->channel->mutex);
locked = 0;
ftdm_thread_create_detached(ftdm_analog_channel_run, event->channel);
} else {
ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG,
"Ignoring polarity reversal because this channel is down\n");
}
break;
}
/* we have a good channel, set the polarity flag and let the channel thread deal with it */
@@ -204,6 +204,32 @@ static int parse_debug(const char *in, uint32_t *flags)
return res;
}
/**
* \brief Parses a change status string to flags
* \param in change status string to parse for
* \return Flags
*/
static int parse_change_status(const char *in)
{
int flags = 0;
if (!in) {
return 0;
}
if (strstr(in, "in_service") || strstr(in, "in")) {
flags = SERVICE_CHANGE_STATUS_INSERVICE;
}
if (strstr(in, "maintenance") || strstr(in, "maint")) {
flags = SERVICE_CHANGE_STATUS_MAINTENANCE;
}
if (strstr(in, "out_of_service") || strstr(in, "out")) {
flags = SERVICE_CHANGE_STATUS_OUTOFSERVICE;
}
return flags;
}
static int print_debug(uint32_t flags, char *tmp, const int size)
{
int offset = 0;
@@ -240,6 +266,9 @@ static ftdm_io_interface_t ftdm_libpri_interface;
static const char *ftdm_libpri_usage =
"Usage:\n"
"libpri kill <span>\n"
"libpri reset <span>\n"
"libpri restart <span> <channel/all>\n"
"libpri maintenance <span> <channel/all> <in/maint/out>\n"
"libpri debug <span> [all|none|flag,...flagN]\n"
"\n"
"Possible debug flags:\n"
@@ -281,9 +310,7 @@ static FIO_API_FUNCTION(ftdm_libpri_api)
stream->write_function(stream, ftdm_libpri_usage);
goto done;
}
}
if (argc == 2) {
} else if (argc == 2) {
if (!strcasecmp(argv[0], "kill")) {
int span_id = atoi(argv[1]);
ftdm_span_t *span = NULL;
@@ -292,7 +319,8 @@ static FIO_API_FUNCTION(ftdm_libpri_api)
ftdm_libpri_data_t *isdn_data = span->signal_data;
if (span->start != ftdm_libpri_start) {
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n",
__FILE__, ftdm_span_get_name(span));
goto done;
}
@@ -300,13 +328,12 @@ static FIO_API_FUNCTION(ftdm_libpri_api)
stream->write_function(stream, "%s: +OK killed.\n", __FILE__);
goto done;
} else {
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
stream->write_function(stream, "%s: -ERR span '%s' not found.\n",
__FILE__, argv[0]);
goto done;
}
}
}
if (argc >= 2) {
} else if (argc >= 2) {
if (!strcasecmp(argv[0], "debug")) {
ftdm_span_t *span = NULL;
@@ -315,7 +342,8 @@ static FIO_API_FUNCTION(ftdm_libpri_api)
uint32_t flags = 0;
if (span->start != ftdm_libpri_start) {
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n",
__FILE__, ftdm_span_get_name(span));
goto done;
}
@@ -335,12 +363,95 @@ static FIO_API_FUNCTION(ftdm_libpri_api)
stream->write_function(stream, "%s: +OK debug %s.\n", __FILE__, (flags) ? "enabled" : "disabled");
goto done;
} else {
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
stream->write_function(stream, "%s: -ERR span '%s' not found.\n",
__FILE__, argv[0]);
goto done;
}
}
if (!strcasecmp(argv[0], "reset")) {
ftdm_span_t *span = NULL;
if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) {
ftdm_libpri_data_t *isdn_data = span->signal_data;
if (span->start != ftdm_libpri_start) {
stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n",
__FILE__, ftdm_span_get_name(span));
goto done;
}
pri_restart(isdn_data->spri.pri);
stream->write_function(stream, "%s: +OK reset.\n", __FILE__);
goto done;
} else {
stream->write_function(stream, "%s: -ERR span '%s' not found.\n",
__FILE__, argv[0]);
goto done;
}
}
if (!strcasecmp(argv[0], "restart") && argc == 3) {
ftdm_span_t *span = NULL;
if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) {
ftdm_libpri_data_t *isdn_data = span->signal_data;
if (span->start != ftdm_libpri_start) {
stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n",
__FILE__, ftdm_span_get_name(span));
goto done;
}
if (!strcasecmp(argv[2], "all")) {
int j;
for(j = 1; j <= span->chan_count; j++) {
pri_reset(isdn_data->spri.pri, j);
ftdm_sleep(50);
}
} else {
pri_reset(isdn_data->spri.pri, atoi(argv[2]));
}
stream->write_function(stream, "%s: +OK restart set.\n", __FILE__);
goto done;
} else {
stream->write_function(stream, "%s: -ERR span '%s' not found.\n",
__FILE__, argv[0]);
goto done;
}
}
if (!strcasecmp(argv[0], "maintenance") && argc > 3) {
ftdm_span_t *span = NULL;
if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) {
ftdm_libpri_data_t *isdn_data = span->signal_data;
if (span->start != ftdm_libpri_start) {
stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n",
__FILE__, ftdm_span_get_name(span));
goto done;
}
if (!isdn_data->service_message_support) {
stream->write_function(stream, "%s: -ERR service message support is disabled\n", __FILE__);
goto done;
}
if (!strcasecmp(argv[2], "all")) {
int j;
for(j = 1; j <= span->chan_count; j++) {
pri_maintenance_service(isdn_data->spri.pri, atoi(argv[1]), j, parse_change_status(argv[3]));
ftdm_sleep(50);
}
} else {
pri_maintenance_service(isdn_data->spri.pri, atoi(argv[1]), atoi(argv[2]), parse_change_status(argv[3]));
}
stream->write_function(stream, "%s: +OK change status set.\n", __FILE__);
goto done;
} else {
stream->write_function(stream, "%s: -ERR span '%s' not found.\n",
__FILE__, argv[0]);
goto done;
}
}
} else {
/* zero args print usage */
stream->write_function(stream, ftdm_libpri_usage);
goto done;
}
stream->write_function(stream, "%s: -ERR invalid command.\n", __FILE__);
done:
@@ -1066,7 +1177,7 @@ static int on_proceeding(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_
if (chan) {
/* Open channel if inband information is available */
if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE || pevent->proceeding.progressmask & PRI_PROG_CALL_NOT_E2E_ISDN) {
ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, B-Channel %d:%d\n",
ftdm_channel_get_span_id(chan),
ftdm_channel_get_id(chan));
@@ -1108,7 +1219,7 @@ static int on_progress(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev
if (chan) {
/* Open channel if inband information is available */
if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE || pevent->proceeding.progressmask & PRI_PROG_CALL_NOT_E2E_ISDN) {
ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, B-Channel %d:%d\n",
ftdm_channel_get_span_id(chan),
ftdm_channel_get_id(chan));
@@ -1780,6 +1891,10 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
pri_facility_enable(isdn_data->spri.pri);
}
#endif
/* Support the different switch of service status */
if (isdn_data->service_message_support) {
pri_set_service_message_support(isdn_data->spri.pri, 1 /* True */);
}
if (res == 0) {
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANY, on_anything);
@@ -1835,6 +1950,14 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
ftdm_sleep(5000);
}
out:
/* close d-channel, if set */
if (isdn_data->dchan) {
if (ftdm_channel_close(&isdn_data->dchan) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Failed to close D-Channel %d:%d\n",
ftdm_channel_get_span_id(isdn_data->dchan), ftdm_channel_get_id(isdn_data->dchan));
}
}
ftdm_log(FTDM_LOG_DEBUG, "PRI thread ended on span %d\n", ftdm_span_get_id(span));
ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
@@ -2159,6 +2282,11 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
isdn_data->debug_mask = 0;
}
}
else if (!strcasecmp(var, "service_message_support")) {
if (ftdm_true(val)) {
isdn_data->service_message_support = 1;
}
}
else {
ftdm_log(FTDM_LOG_ERROR, "Unknown parameter '%s', aborting configuration\n", var);
snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var);
@@ -31,6 +31,11 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
typedef enum {
SERVICE_CHANGE_STATUS_INSERVICE = 0,
SERVICE_CHANGE_STATUS_MAINTENANCE = 1,
SERVICE_CHANGE_STATUS_OUTOFSERVICE = 2
} service_change_status_t;
#ifndef FTMOD_LIBPRI_H
#define FTMOD_LIBPRI_H
@@ -69,6 +74,7 @@ struct ftdm_libpri_data {
int overlap; /*!< Overlap dial flags */
unsigned int layer1;
unsigned int ton;
unsigned int service_message_support;
lpwrap_pri_t spri;
};
File diff suppressed because it is too large. Load diff
@@ -547,7 +547,7 @@ static void handle_pri_passive_event(pritap_t *pritap, pri_event *e)
break;
case PRI_EVENT_PROGRESS:
crv = tap_pri_get_crv(pritap->pri, e->ring.call);
crv = tap_pri_get_crv(pritap->pri, e->proceeding.call);
ftdm_log(FTDM_LOG_DEBUG, "Progress on channel %s:%d:%d with callref %d\n",
pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
break;
@@ -1155,6 +1155,77 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
return FTDM_FAIL;
}
if (span_data->cid_name_method == SNGISDN_CID_NAME_AUTO) {
switch (span_data->switchtype) {
case SNGISDN_SWITCH_EUROISDN:
if (FTDM_SPAN_IS_BRI(span)) {
span_data->cid_name_method = SNGISDN_CID_NAME_USR_USR_IE;
} else {
span_data->cid_name_method = SNGISDN_CID_NAME_DISPLAY_IE;
}
break;
case SNGISDN_SWITCH_DMS100:
span_data->cid_name_method = SNGISDN_CID_NAME_DISPLAY_IE;
break;
case SNGISDN_SWITCH_NI2:
case SNGISDN_SWITCH_5ESS:
case SNGISDN_SWITCH_4ESS:
span_data->cid_name_method = SNGISDN_CID_NAME_FACILITY_IE;
break;
default:
break;
}
}
if (span_data->send_cid_name == SNGISDN_OPT_DEFAULT) {
switch (span_data->switchtype) {
case SNGISDN_SWITCH_EUROISDN:
#ifdef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY
case SNGISDN_SWITCH_NI2:
case SNGISDN_SWITCH_5ESS:
case SNGISDN_SWITCH_4ESS:
#endif
if (span_data->signalling == SNGISDN_SIGNALING_NET) {
span_data->send_cid_name = SNGISDN_OPT_TRUE;
} else {
span_data->send_cid_name = SNGISDN_OPT_FALSE;
}
break;
case SNGISDN_SWITCH_DMS100:
span_data->send_cid_name = SNGISDN_OPT_TRUE;
break;
#ifndef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY
case SNGISDN_SWITCH_NI2:
case SNGISDN_SWITCH_5ESS:
case SNGISDN_SWITCH_4ESS:
span_data->send_cid_name = SNGISDN_OPT_FALSE;
break;
#endif
default:
span_data->send_cid_name = SNGISDN_OPT_FALSE;
break;
}
} else if (span_data->send_cid_name == SNGISDN_OPT_TRUE) {
switch (span_data->switchtype) {
case SNGISDN_SWITCH_NI2:
case SNGISDN_SWITCH_5ESS:
case SNGISDN_SWITCH_4ESS:
#ifndef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY
ftdm_log(FTDM_LOG_WARNING, "Sending Calling Name in Facility IE not supported, please update your libsng_isdn library\n");
span_data->send_cid_name = SNGISDN_OPT_FALSE;
#endif
break;
case SNGISDN_SWITCH_INSNET: /* Don't know how to transmit caller ID name on INSNET */
case SNGISDN_SWITCH_QSIG: /* It seems like QSIG does not support Caller ID */
span_data->send_cid_name = SNGISDN_OPT_FALSE;
break;
case SNGISDN_SWITCH_EUROISDN:
break;
default:
span_data->send_cid_name = SNGISDN_OPT_FALSE;
break;
}
}
span->start = ftdm_sangoma_isdn_start;
span->stop = ftdm_sangoma_isdn_stop;
@@ -132,6 +132,13 @@ typedef enum {
SNGISDN_AVAIL_UP = 10,
} sngisdn_avail_t;
typedef enum {
SNGISDN_CID_NAME_AUTO,
SNGISDN_CID_NAME_DISPLAY_IE,
SNGISDN_CID_NAME_USR_USR_IE,
SNGISDN_CID_NAME_FACILITY_IE,
} sngisdn_cid_name_t;
typedef enum {
SNGISDN_EVENT_CON_IND = 1,
SNGISDN_EVENT_CON_CFM,
@@ -264,6 +271,8 @@ typedef struct sngisdn_span_data {
uint8_t restart_opt;
uint8_t restart_timeout;
uint8_t force_sending_complete;
uint8_t cid_name_method;
uint8_t send_cid_name;
char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
ftdm_timer_id_t timers[SNGISDN_NUM_SPAN_TIMERS];
ftdm_sched_t *sched;
@@ -289,6 +289,9 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
signal_data->att_remove_dtmf = SNGISDN_OPT_DEFAULT;
signal_data->force_sending_complete = SNGISDN_OPT_DEFAULT;
signal_data->cid_name_method = SNGISDN_CID_NAME_AUTO;
signal_data->send_cid_name = SNGISDN_OPT_DEFAULT;
span->default_caller_data.dnis.plan = FTDM_NPI_INVALID;
span->default_caller_data.dnis.type = FTDM_TON_INVALID;
span->default_caller_data.cid_num.plan = FTDM_NPI_INVALID;
@@ -361,7 +364,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
parse_yesno(var, val, &signal_data->restart_opt);
} else if (!strcasecmp(var, "channel-restart-timeout")) {
signal_data->restart_timeout = atoi(val);
} else if (!strcasecmp(var, "local-number")) {
} else if (!strcasecmp(var, "local-number")) {
if (add_local_number(val, span) != FTDM_SUCCESS) {
return FTDM_FAIL;
}
@@ -401,6 +404,30 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
#else
ftdm_log(FTDM_LOG_WARNING, "chan-id-invert-extend-bit is not supported in your version of libsng_isdn\n");
#endif
} else if (!strcasecmp(var, "cid-name-transmit-method")) {
if (!strcasecmp(val, "display-ie")) {
signal_data->cid_name_method = SNGISDN_CID_NAME_DISPLAY_IE;
} else if (!strcasecmp(val, "user-user-ie")) {
signal_data->cid_name_method = SNGISDN_CID_NAME_USR_USR_IE;
} else if (!strcasecmp(val, "facility-ie")) {
signal_data->cid_name_method = SNGISDN_CID_NAME_FACILITY_IE;
} else if (!strcasecmp(val, "auto") || !strcasecmp(val, "automatic") || !strcasecmp(val, "default")) {
signal_data->cid_name_method = SNGISDN_CID_NAME_AUTO;
} else {
ftdm_log(FTDM_LOG_WARNING, "Invalid option %s for parameter %s\n", val, var);
signal_data->cid_name_method = SNGISDN_CID_NAME_AUTO;
}
} else if (!strcasecmp(var, "send-cid-name")) {
if (!strcasecmp(val, "yes")) {
signal_data->send_cid_name = SNGISDN_OPT_TRUE;
} else if (!strcasecmp(val, "no")) {
signal_data->send_cid_name = SNGISDN_OPT_FALSE;
} else if (!strcasecmp(val, "auto") || !strcasecmp(val, "automatic") || !strcasecmp(val, "default")) {
signal_data->send_cid_name = SNGISDN_OPT_DEFAULT;
} else {
ftdm_log(FTDM_LOG_WARNING, "Invalid option %s for parameter %s\n", val, var);
signal_data->send_cid_name = SNGISDN_OPT_DEFAULT;
}
} else {
ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
}
@@ -681,7 +681,11 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.clrGlr = FALSE; /* in case of glare, do not clear local call */
cfg.t.cfg.s.inDLSAP.statEnqOpt = TRUE;
cfg.t.cfg.s.inDLSAP.rstOpt = TRUE;
if (signal_data->ftdm_span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
cfg.t.cfg.s.inDLSAP.rstOpt = FALSE;
} else {
cfg.t.cfg.s.inDLSAP.rstOpt = TRUE;
}
} else {
cfg.t.cfg.s.inDLSAP.ackOpt = FALSE;
cfg.t.cfg.s.inDLSAP.intType = USER;
@@ -772,15 +776,13 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.tmr.t307.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t308.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t308.val = 4;
cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t310.val = 120;
if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t310.val = 10;
cfg.t.cfg.s.inDLSAP.tmr.t312.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t312.val = cfg.t.cfg.s.inDLSAP.tmr.t303.val+2;
} else {
cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t310.val = 120;
cfg.t.cfg.s.inDLSAP.tmr.t312.enb = FALSE;
}
@@ -846,7 +848,7 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.dChannelNum = 0; /* Unused for BRI */
cfg.t.cfg.s.inDLSAP.nmbBearChan = NUM_BRI_CHANNELS_PER_SPAN;
cfg.t.cfg.s.inDLSAP.firstBChanNum = 1;
cfg.t.cfg.s.inDLSAP.callRefLen = 1;
cfg.t.cfg.s.inDLSAP.callRefLen = 1;
cfg.t.cfg.s.inDLSAP.teiAlloc = IN_STATIC;
cfg.t.cfg.s.inDLSAP.intCfg = IN_INTCFG_PTPT;
break;
@@ -902,7 +904,14 @@ ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span)
cfg.t.cfg.s.inLCe.sapId = signal_data->dchan_id;
cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE;
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
/* Stack will send Restart CFM's each time link is established (TEI negotiated),
and we do not want thi s event */
cfg.t.cfg.s.inLCe.lnkUpDwnInd = FALSE;
} else {
cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE;
}
cfg.t.cfg.s.inLCe.tCon.enb = TRUE;
cfg.t.cfg.s.inLCe.tCon.val = 35;
cfg.t.cfg.s.inLCe.tDisc.enb = TRUE;
@@ -1178,7 +1178,16 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
ftdm_log(FTDM_LOG_CRIT, "Received RESTART CFM on unconfigured span (suId:%d)\n", suId);
return;
}
ftdm_log(FTDM_LOG_DEBUG, "%s: Processing RESTART CFM (suId:%u dChan:%d ces:%d %s(%d))\n",
signal_data->ftdm_span->name,
suId, dChan, ces,
(evntType == IN_LNK_DWN)?"LNK_DOWN":
(evntType == IN_LNK_UP)?"LNK_UP":
(evntType == IN_INDCHAN)?"b-channel":
(evntType == IN_LNK_DWN_DM_RLS)?"NFAS service procedures":
(evntType == IN_SWCHD_BU_DCHAN)?"NFAS switchover to backup":"Unknown", evntType);
if (rstEvnt->rstInd.eh.pres == PRSNT_NODEF && rstEvnt->rstInd.rstClass.pres == PRSNT_NODEF) {
switch(rstEvnt->rstInd.rstClass.val) {
case IN_CL_INDCHAN: /* Indicated b-channel */
@@ -1212,19 +1221,29 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
}
if (chan_no) { /* For a single channel */
if (chan_no > ftdm_span_get_chan_count(signal_data->ftdm_span)) {
ftdm_log(FTDM_LOG_CRIT, "Received RESTART on invalid channel:%d\n", chan_no);
} else {
ftdm_channel_t *ftdmchan = ftdm_span_get_channel(signal_data->ftdm_span, chan_no);
sngisdn_bring_down(ftdmchan);
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
if (sngisdn_info->ces == ces && ftdmchan->physical_chan_id == chan_no) {
sngisdn_bring_down(ftdmchan);
}
}
ftdm_iterator_free(chaniter);
} else { /* for all channels */
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
sngisdn_bring_down((ftdm_channel_t*)ftdm_iterator_current(curr));
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
if (sngisdn_info->ces == ces) {
sngisdn_bring_down(ftdmchan);
}
}
ftdm_iterator_free(chaniter);
}
@@ -1305,28 +1324,29 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
}
if (chan_no) { /* For a single channel */
if (chan_no > ftdm_span_get_chan_count(signal_data->ftdm_span)) {
ftdm_log(FTDM_LOG_CRIT, "Received RESTART IND on invalid channel:%d\n", chan_no);
} else {
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
if (ftdmchan->physical_chan_id == chan_no) {
sngisdn_bring_down(ftdmchan);
}
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
if (sngisdn_info->ces == ces && ftdmchan->physical_chan_id == chan_no) {
sngisdn_bring_down(ftdmchan);
}
ftdm_iterator_free(chaniter);
}
ftdm_iterator_free(chaniter);
} else { /* for all channels */
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
sngisdn_bring_down((ftdm_channel_t*)ftdm_iterator_current(curr));
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
if (sngisdn_info->ces == ces) {
sngisdn_bring_down(ftdmchan);
}
}
ftdm_iterator_free(chaniter);
}
@@ -69,6 +69,8 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad);
set_redir_num(ftdmchan, &conEvnt.redirNmb);
set_calling_name(ftdmchan, &conEvnt);
/* set_facility_ie will overwrite Calling Name for NI-2 if user specifies custom Facility IE */
set_facility_ie(ftdmchan, &conEvnt.facilityStr);
set_prog_ind_ie(ftdmchan, &conEvnt.progInd, prog_ind);
@@ -897,12 +897,19 @@ int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame)
do {
flags = FTDM_WRITE;
status = signal_data->dchan->fio->wait(signal_data->dchan, &flags, 1000);
if (status != FTDM_SUCCESS) {
ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_WARNING, "transmit timed-out\n");
return -1;
switch(status) {
case FTDM_SUCCESS:
break;
case FTDM_TIMEOUT:
continue;
case FTDM_FAIL:
default:
ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_WARNING, "failed to poll for channel\n");
return -1;
}
/* status = FTDM_SUCCESS */
if ((flags & FTDM_WRITE)) {
#if 0
int i;
@@ -990,27 +997,29 @@ void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...)
switch (level) {
case SNG_LOGLEVEL_DEBUG:
ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s\n", data);
break;
case SNG_LOGLEVEL_WARN:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
if ( strncmp(data, "Invalid Q.921/Q.931 frame", 25) ) {
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
}
break;
case SNG_LOGLEVEL_INFO:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data);
break;
case SNG_LOGLEVEL_STATS:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data);
break;
case SNG_LOGLEVEL_ERROR:
ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s\n", data);
/*ftdm_assert(0, "Got an error from stack");*/
break;
case SNG_LOGLEVEL_CRIT:
ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s\n", data);
/* ftdm_assert(0, "Got an error from stack"); */
break;
default:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data);
break;
}
ftdm_safe_free(data);
@@ -567,7 +567,7 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.digits");
if ((string == NULL) || !(*string)) {
if (ftdm_strlen_zero(string)) {
return FTDM_FAIL;
}
@@ -696,63 +696,71 @@ ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb)
ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt)
{
uint8_t len;
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
/* sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; */
const char *string = NULL;
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
ftdm_bool_t force_send_cid_name = FTDM_FALSE;
len = strlen(caller_data->cid_name);
if (!len) {
return FTDM_SUCCESS;
}
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
conEvnt->usrUsr.eh.pres = PRSNT_NODEF;
conEvnt->usrUsr.protocolDisc.pres = PRSNT_NODEF;
conEvnt->usrUsr.protocolDisc.val = PD_IA5; /* IA5 chars */
conEvnt->usrUsr.usrInfo.pres = PRSNT_NODEF;
conEvnt->usrUsr.usrInfo.len = len;
/* in sangoma_brid we used to send usr-usr info as <cid_name>!<calling_number>,
change to previous style if current one does not work */
memcpy(conEvnt->usrUsr.usrInfo.val, caller_data->cid_name, len);
} else {
switch (signal_data->switchtype) {
case SNGISDN_SWITCH_NI2:
/* TODO: Need to send the caller ID as a facility IE */
break;
case SNGISDN_SWITCH_EUROISDN:
if (signal_data->signalling != SNGISDN_SIGNALING_NET) {
break;
}
/* follow through */
case SNGISDN_SWITCH_5ESS:
case SNGISDN_SWITCH_4ESS:
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;
case SNGISDN_SWITCH_INSNET:
/* Don't know how to transmit caller ID name on INSNET */
break;
string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.send_cid_name");
if (!ftdm_strlen_zero(string)) {
if (!strcasecmp(string, "no")) {
return FTDM_SUCCESS;
} else if (!strcasecmp(string, "yes")) {
force_send_cid_name = FTDM_TRUE;
}
}
if (force_send_cid_name == FTDM_FALSE && signal_data->send_cid_name == SNGISDN_OPT_FALSE) {
return FTDM_SUCCESS;
}
switch(signal_data->cid_name_method) {
case SNGISDN_CID_NAME_FACILITY_IE:
#ifdef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY
/* Note: The Facility IE will be overwritten if user chose to transmit a Raw Facility IE */
sng_isdn_encode_facility_caller_name(caller_data->cid_name, conEvnt->facilityStr.facilityStr.val, &conEvnt->facilityStr.facilityStr.len);
conEvnt->facilityStr.eh.pres = PRSNT_NODEF;
conEvnt->facilityStr.facilityStr.pres = PRSNT_NODEF;
#endif
break;
case SNGISDN_CID_NAME_USR_USR_IE:
conEvnt->usrUsr.eh.pres = PRSNT_NODEF;
conEvnt->usrUsr.protocolDisc.pres = PRSNT_NODEF;
conEvnt->usrUsr.protocolDisc.val = PD_IA5; /* IA5 chars */
conEvnt->usrUsr.usrInfo.pres = PRSNT_NODEF;
conEvnt->usrUsr.usrInfo.len = len;
/* in sangoma_brid we used to send usr-usr info as <cid_name>!<calling_number>,
change to previous style if current one does not work */
memcpy(conEvnt->usrUsr.usrInfo.val, caller_data->cid_name, len);
break;
case SNGISDN_CID_NAME_DISPLAY_IE:
if (signal_data->switchtype == 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);
} else {
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;
default:
break;
}
return FTDM_SUCCESS;
}
@@ -760,7 +768,7 @@ ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
{
const char* clg_subaddr = NULL;
clg_subaddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.calling_subaddr");
if ((clg_subaddr != NULL) && (*clg_subaddr)) {
if (!ftdm_strlen_zero(clg_subaddr)) {
unsigned len = strlen (clg_subaddr);
cgPtySad->eh.pres = PRSNT_NODEF;
cgPtySad->typeSad.pres = 1;
@@ -249,6 +249,34 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
SS7_DEBUG_CHAN(ftdmchan, "No Location Number information in IAM%s\n", " ");
}
/* Retrieve the Location Number if present (see ITU Q.763, 3.30) */
if (siConEvnt->cgPtyNum1.eh.pres) {
if (siConEvnt->cgPtyNum1.addrSig.pres) {
/* fill in the ss7 location address number */
copy_tknStr_from_sngss7(siConEvnt->cgPtyNum1.addrSig, var, siConEvnt->cgPtyNum1.oddEven);
sngss7_add_var(sngss7_info, "ss7_loc_digits", var);
}
if (siConEvnt->cgPtyNum1.scrnInd.pres) {
/* fill in the screening indication value */
sprintf(var, "%d", siConEvnt->cgPtyNum1.scrnInd.val);
sngss7_add_var(sngss7_info, "ss7_loc_screen_ind", var);
}
if (siConEvnt->cgPtyNum1.presRest.pres) {
/* fill in the presentation value */
sprintf(var, "%d", siConEvnt->cgPtyNum1.presRest.val);
sngss7_add_var(sngss7_info, "ss7_loc_pres_ind", var);
}
if (siConEvnt->cgPtyNum1.natAddrInd.pres) {
sprintf(var, "%d", siConEvnt->cgPtyNum1.natAddrInd.val);
sngss7_add_var(sngss7_info, "ss7_loc_nadi", var);
}
} else {
SS7_DEBUG_CHAN(ftdmchan, "No Location Number information in IAM%s\n", " ");
}
sprintf(var, "%d", sngss7_info->circuit->cic);
sngss7_add_var(sngss7_info, "ss7_cic", var);
@@ -256,11 +284,10 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sngss7_add_var(sngss7_info, "ss7_opc", var);
if (siConEvnt->callRef.callId.pres) {
/* %x expect an unsigned int so as callId is a U32, casting to uint32_t
* is safe */
sprintf(var, "%x", (uint32_t)siConEvnt->callRef.callId.val);
sngss7_add_var(sngss7_info, "ss7_callref", var);
}
ftdmchan->caller_data.call_reference = (unsigned int)siConEvnt->callRef.callId.val;
} else {
ftdmchan->caller_data.call_reference = 0;
}
if (sngss7_info->circuit->transparent_iam) {
sngss7_save_iam(ftdmchan, siConEvnt);
@@ -39,6 +39,11 @@
*
*/
#ifdef WP_DEBUG_IO
#define _BSD_SOURCE
#include <syscall.h>
#endif
#ifdef __sun
#include <unistd.h>
#include <stropts.h>
@@ -99,6 +104,17 @@ static struct {
uint32_t ring_off_ms;
} wp_globals;
typedef struct {
sangoma_wait_obj_t *waitobj;
#ifdef WP_DEBUG_IO
/* record the last reader threads */
pid_t readers[10];
int rindex;
ftdm_time_t last_read;
#endif
} wp_channel_t;
#define WP_GET_WAITABLE(fchan) ((wp_channel_t *)((fchan)->io_data))->waitobj
/* a bunch of this stuff should go into the wanpipe_tdm_api_iface.h */
FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event);
@@ -123,7 +139,7 @@ static __inline__ int tdmv_api_wait_socket(ftdm_channel_t *ftdmchan, int timeout
int err;
uint32_t inflags = *flags;
uint32_t outflags = 0;
sangoma_wait_obj_t *sangoma_wait_obj = ftdmchan->io_data;
sangoma_wait_obj_t *sangoma_wait_obj = WP_GET_WAITABLE(ftdmchan);
if (timeout == -1) {
timeout = SANGOMA_WAIT_INFINITE;
@@ -254,9 +270,13 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
}
if (ftdm_span_add_channel(span, sockfd, type, &chan) == FTDM_SUCCESS) {
wp_channel_t *wpchan = NULL;
wanpipe_tdm_api_t tdm_api;
memset(&tdm_api, 0, sizeof(tdm_api));
#ifdef LIBSANGOMA_VERSION
wpchan = ftdm_calloc(1, sizeof(*wpchan));
ftdm_assert(wpchan != NULL, "wpchan alloc failed\n");
chan->io_data = wpchan;
/* we need SANGOMA_DEVICE_WAIT_OBJ_SIG and not SANGOMA_DEVICE_WAIT_OBJ alone because we need to call
* sangoma_wait_obj_sig to wake up any I/O waiters when closing the channel (typically on ftdm shutdown)
* this adds an extra pair of file descriptors to the waitable object
@@ -266,7 +286,7 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
ftdm_log(FTDM_LOG_ERROR, "failure create waitable object for s%dc%d\n", spanno, x);
continue;
}
chan->io_data = sangoma_wait_obj;
WP_GET_WAITABLE(chan) = sangoma_wait_obj;
#endif
chan->physical_span_id = spanno;
@@ -580,9 +600,16 @@ static FIO_OPEN_FUNCTION(wanpipe_open)
static FIO_CLOSE_FUNCTION(wanpipe_close)
{
#ifdef LIBSANGOMA_VERSION
sangoma_wait_obj_t *waitobj = ftdmchan->io_data;
sangoma_wait_obj_t *waitobj = WP_GET_WAITABLE(ftdmchan);
/* kick any I/O waiters */
sangoma_wait_obj_signal(waitobj);
#ifdef WP_DEBUG_IO
{
wp_channel_t *wchan = ftdmchan->io_data;
memset(wchan->readers, 0, sizeof(wchan->readers));
wchan->rindex = 0;
}
#endif
#endif
return FTDM_SUCCESS;
}
@@ -944,10 +971,44 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx
static FIO_READ_FUNCTION(wanpipe_read)
{
int rx_len = 0;
int rq_len = (int)*datalen;
wp_tdm_api_rx_hdr_t hdrframe;
memset(&hdrframe, 0, sizeof(hdrframe));
#ifdef WP_DEBUG_IO
wp_channel_t *wchan = ftdmchan->io_data;
ftdm_time_t time_diff = 0;
pid_t previous_thread = 1;
pid_t current_thread = 0;
int previous_thread_index = 0;
previous_thread_index = wchan->rindex == 0 ? (ftdm_array_len(wchan->readers) - 1) : wchan->rindex - 1;
previous_thread = wchan->readers[previous_thread_index];
current_thread = syscall(SYS_gettid);
if (current_thread && current_thread != wchan->readers[wchan->rindex]) {
if (!wchan->readers[wchan->rindex]) {
wchan->readers[wchan->rindex] = current_thread;
/* first read */
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Initial reader thread is %d\n", current_thread);
previous_thread = current_thread;
} else {
previous_thread = wchan->readers[wchan->rindex];
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Changed reader thread from %d to %d (rindex = %d)\n",
previous_thread, current_thread, wchan->rindex);
if (wchan->rindex == (ftdm_array_len(wchan->readers) - 1)) {
wchan->rindex = 0;
} else {
wchan->rindex++;
}
wchan->readers[wchan->rindex] = current_thread;
}
}
ftdm_time_t curr = ftdm_current_time_in_ms();
if (wchan->last_read) {
time_diff = curr - wchan->last_read;
}
#endif
memset(&hdrframe, 0, sizeof(hdrframe));
rx_len = sangoma_readmsg_tdm(ftdmchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (int)*datalen, 0);
*datalen = rx_len;
@@ -957,14 +1018,20 @@ static FIO_READ_FUNCTION(wanpipe_read)
}
if (rx_len < 0) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno));
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read from sangoma device: %s (%d)\n", strerror(errno), rx_len);
#ifdef WP_DEBUG_IO
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read %d bytes from sangoma device: %s (%d) "
"(read time diff = %llums, prev thread = %d, curr thread = %d)\n", rq_len, strerror(errno), rx_len,
time_diff, previous_thread, current_thread);
#else
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read %d bytes from sangoma device: %s (%d)\n", rq_len, strerror(errno), rx_len);
#endif
return FTDM_FAIL;
}
if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) {
wanpipe_read_stats(ftdmchan, &hdrframe);
}
return FTDM_SUCCESS;
}
@@ -1110,7 +1177,7 @@ FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
if (!ftdmchan->io_data) {
continue; /* should never happen but happens when shutting down */
}
pfds[j] = ftdmchan->io_data;
pfds[j] = WP_GET_WAITABLE(ftdmchan);
inflags[j] = chan_events;
#else
memset(&pfds[j], 0, sizeof(pfds[j]));
@@ -1572,10 +1639,10 @@ static FIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
{
#ifdef LIBSANGOMA_VERSION
if (ftdmchan->io_data) {
sangoma_wait_obj_t *sangoma_wait_obj;
sangoma_wait_obj = ftdmchan->io_data;
ftdmchan->io_data = NULL;
sangoma_wait_obj_t *sangoma_wait_obj = WP_GET_WAITABLE(ftdmchan);
sangoma_wait_obj_delete(&sangoma_wait_obj);
ftdm_safe_free(ftdmchan->io_data);
ftdmchan->io_data = NULL;
}
#endif
@@ -1606,7 +1673,8 @@ static FIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
*/
static FIO_IO_LOAD_FUNCTION(wanpipe_init)
{
assert(fio != NULL);
ftdm_assert(fio != NULL, "fio should not be null\n");
memset(&wanpipe_interface, 0, sizeof(wanpipe_interface));
wp_globals.codec_ms = 20;
+42 -19
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:
*
* Moises Silva <moy@sangoma.com>
* W McRoberts <fs@whmcr.com>
*
*/
#include "private/ftdm_core.h"
@@ -94,6 +100,7 @@ struct ioctl_codes {
ioctlcmd ECHOTRAIN;
ioctlcmd SETTXBITS;
ioctlcmd GETRXBITS;
ioctlcmd SETPOLARITY;
};
/**
@@ -169,7 +176,8 @@ static struct ioctl_codes dahdi_ioctl_codes = {
.GETCONFMUTE = DAHDI_GETCONFMUTE,
.ECHOTRAIN = DAHDI_ECHOTRAIN,
.SETTXBITS = DAHDI_SETTXBITS,
.GETRXBITS = DAHDI_GETRXBITS
.GETRXBITS = DAHDI_GETRXBITS,
.SETPOLARITY = DAHDI_SETPOLARITY
};
#define ZT_INVALID_SOCKET -1
@@ -248,7 +256,7 @@ static void zt_build_gains(struct zt_gains *g, float rxgain, float txgain, int c
}
/**
* \brief Initialises a range of ftdmtel channels
* \brief Initialises a range of Zaptel/DAHDI channels
* \param span FreeTDM span
* \param start Initial wanpipe channel number
* \param end Final wanpipe channel number
@@ -341,7 +349,7 @@ static unsigned zt_open_range(ftdm_span_t *span, unsigned start, unsigned end, f
}
if (ioctl(CONTROL_FD, codes.CHANCONFIG, &cc)) {
ftdm_log(FTDM_LOG_WARNING, "this ioctl fails on older ftdmtel but is harmless if you used ztcfg\n[device %s chan %d fd %d (%s)]\n", chanpath, x, CONTROL_FD, strerror(errno));
ftdm_log(FTDM_LOG_WARNING, "this ioctl fails in older zaptel but is harmless if you used ztcfg\n[device %s chan %d fd %d (%s)]\n", chanpath, x, CONTROL_FD, strerror(errno));
}
}
@@ -445,7 +453,7 @@ static unsigned zt_open_range(ftdm_span_t *span, unsigned start, unsigned end, f
}
/**
* \brief Initialises an freetdm ftdmtel span from a configuration string
* \brief Initialises a freetdm Zaptel/DAHDI span from a configuration string
* \param span FreeTDM span
* \param str Configuration string
* \param type FreeTDM span type
@@ -515,7 +523,7 @@ static FIO_CONFIGURE_SPAN_FUNCTION(zt_configure_span)
}
/**
* \brief Process configuration variable for a ftdmtel profile
* \brief Process configuration variable for a Zaptel/DAHDI profile
* \param category Wanpipe profile name
* \param var Variable name
* \param val Variable value
@@ -593,7 +601,7 @@ static FIO_CONFIGURE_FUNCTION(zt_configure)
}
/**
* \brief Opens a ftdmtel channel
* \brief Opens a Zaptel/DAHDI channel
* \param ftdmchan Channel to open
* \return Success or failure
*/
@@ -663,7 +671,7 @@ static FIO_OPEN_FUNCTION(zt_open)
}
/**
* \brief Closes ftdmtel channel
* \brief Closes Zaptel/DAHDI channel
* \param ftdmchan Channel to close
* \return Success
*/
@@ -681,7 +689,7 @@ static FIO_CLOSE_FUNCTION(zt_close)
}
/**
* \brief Executes an FreeTDM command on a ftdmtel channel
* \brief Executes a FreeTDM command on a Zaptel/DAHDI channel
* \param ftdmchan Channel to execute command on
* \param command FreeTDM command to execute
* \param obj Object (unused)
@@ -826,6 +834,15 @@ static FIO_COMMAND_FUNCTION(zt_command)
err = ioctl(ftdmchan->sockfd, codes.FLUSH, &flushmode);
}
break;
case FTDM_COMMAND_SET_POLARITY:
{
ftdm_polarity_t polarity = FTDM_COMMAND_OBJ_INT;
err = ioctl(ftdmchan->sockfd, codes.SETPOLARITY, polarity);
if (!err) {
ftdmchan->polarity = polarity;
}
}
break;
case FTDM_COMMAND_FLUSH_RX_BUFFERS:
{
int flushmode = ZT_FLUSH_READ;
@@ -853,7 +870,7 @@ static FIO_COMMAND_FUNCTION(zt_command)
}
/**
* \brief Gets alarms from a ftdmtel Channel
* \brief Gets alarms from a Zaptel/DAHDI channel
* \param ftdmchan Channel to get alarms from
* \return Success or failure
*/
@@ -876,7 +893,7 @@ static FIO_GET_ALARMS_FUNCTION(zt_get_alarms)
}
/**
* \brief Waits for an event on a ftdmtel channel
* \brief Waits for an event on a Zaptel/DAHDI channel
* \param ftdmchan Channel to open
* \param flags Type of event to wait for
* \param to Time to wait (in ms)
@@ -950,7 +967,7 @@ pollagain:
}
/**
* \brief Checks for events on a ftdmtel span
* \brief Checks for events on a Zaptel/DAHDI span
* \param span Span to check for events
* \param ms Time to wait for event
* \return Success if event is waiting or failure if not
@@ -1088,6 +1105,12 @@ static __inline__ ftdm_status_t zt_channel_process_event(ftdm_channel_t *fchan,
*event_id = FTDM_OOB_NOOP; /* What else could we do? */
}
break;
case ZT_EVENT_POLARITY:
{
ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Got polarity reverse (ZT_EVENT_POLARITY)\n");
*event_id = FTDM_OOB_POLARITY_REVERSE;
}
break;
case ZT_EVENT_NONE:
{
ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "No event\n");
@@ -1141,7 +1164,7 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(zt_channel_next_event)
}
/**
* \brief Retrieves an event from a ftdmtel span
* \brief Retrieves an event from a Zaptel/DAHDI span
* \param span Span to retrieve event from
* \param event FreeTDM event to return
* \return Success or failure
@@ -1181,7 +1204,7 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event)
}
/**
* \brief Reads data from a ftdmtel channel
* \brief Reads data from a Zaptel/DAHDI channel
* \param ftdmchan Channel to read from
* \param data Data buffer
* \param datalen Size of data buffer
@@ -1223,7 +1246,7 @@ static FIO_READ_FUNCTION(zt_read)
}
/**
* \brief Writes data to a ftdmtel channel
* \brief Writes data to a Zaptel/DAHDI channel
* \param ftdmchan Channel to write to
* \param data Data buffer
* \param datalen Size of data buffer
@@ -1262,7 +1285,7 @@ tryagain:
}
/**
* \brief Destroys a ftdmtel Channel
* \brief Destroys a Zaptel/DAHDI Channel
* \param ftdmchan Channel to destroy
* \return Success
*/
@@ -1275,12 +1298,12 @@ static FIO_CHANNEL_DESTROY_FUNCTION(zt_channel_destroy)
}
/**
* \brief Global FreeTDM IO interface for ftdmtel
* \brief Global FreeTDM IO interface for Zaptel/DAHDI
*/
static ftdm_io_interface_t zt_interface;
/**
* \brief Loads ftdmtel IO module
* \brief Loads Zaptel/DAHDI IO module
* \param fio FreeTDM IO interface
* \return Success or failure
*/
@@ -1335,7 +1358,7 @@ static FIO_IO_LOAD_FUNCTION(zt_init)
}
/**
* \brief Unloads ftdmtel IO module
* \brief Unloads Zaptel/DAHDI IO module
* \return Success
*/
static FIO_IO_UNLOAD_FUNCTION(zt_destroy)
@@ -1346,7 +1369,7 @@ static FIO_IO_UNLOAD_FUNCTION(zt_destroy)
}
/**
* \brief FreeTDM ftdmtel IO module definition
* \brief FreeTDM Zaptel/DAHDI IO module definition
*/
ftdm_module_t ftdm_module = {
"zt",
@@ -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:
*
* Moises Silva <moy@sangoma.com>
* W McRoberts <fs@whmcr.com>
*
*/
#ifndef FTDM_ZT_H
@@ -349,6 +355,7 @@ ZT_ABIT = 8
#define DAHDI_SETTXBITS _IOW (DAHDI_CODE, 43, int)
#define DAHDI_GETRXBITS _IOR (DAHDI_CODE, 43, int)
#define DAHDI_SETPOLARITY _IOW (DAHDI_CODE, 92, int) /* Polarity setting for FXO lines */
#endif