wanpipe commit we've all been waiting for, HW dtmf, ALARMS, proper bounce of PRIs (testers needed)

git-svn-id: http://svn.openzap.org/svn/openzap/trunk@719 a93c3328-9c30-0410-af19-c9cd2b2d52af
This commit is contained in:
Anthony Minessale 2009-04-22 21:22:42 +00:00
parent a378191ff6
commit 793792d4f8
10 changed files with 414 additions and 437 deletions

View File

@ -154,10 +154,12 @@ ozmod_skel_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
ozmod_skel_la_LDFLAGS = -module -avoid-version
ozmod_skel_la_LIBADD = $(MYLIB)
if LIBSANGOMA
ozmod_wanpipe_la_SOURCES = $(SRC)/ozmod/ozmod_wanpipe/ozmod_wanpipe.c
ozmod_wanpipe_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
ozmod_wanpipe_la_LDFLAGS = -module -avoid-version
ozmod_wanpipe_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -D__LINUX__ -I/usr/include/wanpipe
ozmod_wanpipe_la_LDFLAGS = -module -avoid-version -lsangoma
ozmod_wanpipe_la_LIBADD = $(MYLIB)
endif
ozmod_isdn_la_SOURCES = \
$(SRC)/isdn/EuroISDNStateNT.c \

View File

@ -155,6 +155,9 @@ AC_ARG_WITH([libpri],
[AS_HELP_STRING([--with-libpri], [Install ozmod_libpri])], [enable_libpri="yes"], [enable_libpri="no"])
AC_SUBST(enable_libpri)
AC_CHECK_LIB([sangoma], [sangoma_span_chan_toif], [have_libsangoma="yes"])
AM_CONDITIONAL([LIBSANGOMA],[test "${have_libsangoma}" = "yes"])
AM_CONDITIONAL([LIBPRI],[test "${enable_libpri}" = "yes"])
COMP_VENDOR_CFLAGS="$COMP_VENDOR_CFLAGS"

View File

@ -475,7 +475,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
break;
default:
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled type for channel %s\n", switch_channel_get_name(channel));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unhandled type for channel %s\n", switch_channel_get_name(channel));
}
break;
}

View File

@ -115,9 +115,14 @@ static int __pri_lpwrap_read(struct pri *pri, void *buf, int buflen)
struct lpwrap_pri *spri = (struct lpwrap_pri *) pri_get_userdata(pri);
zap_size_t len = buflen;
int res;
zap_status_t zst;
if (zap_channel_read(spri->dchan, buf, &len) != ZAP_SUCCESS) {
zap_log(ZAP_LOG_CRIT, "span %d D-READ FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error);
if ((zst = zap_channel_read(spri->dchan, buf, &len)) != ZAP_SUCCESS) {
if (zst == ZAP_FAIL) {
zap_log(ZAP_LOG_CRIT, "span %d D-READ FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error);
} else {
zap_log(ZAP_LOG_CRIT, "span %d D-READ TIMEOUT\n", spri->span->span_id);
}
zap_clear_flag(spri, LPWRAP_PRI_READY);
return -1;
}
@ -145,7 +150,7 @@ static int __pri_lpwrap_write(struct pri *pri, void *buf, int buflen)
if (zap_channel_write(spri->dchan, buf, buflen, &len) != ZAP_SUCCESS) {
zap_log(ZAP_LOG_CRIT, "span %d D-WRITE FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error);
zap_clear_flag(spri, LPWRAP_PRI_READY);
return -1;
return -1;
}
#ifdef IODEBUG
@ -198,9 +203,9 @@ int lpwrap_one_loop(struct lpwrap_pri *spri)
}
}
if (!zap_test_flag(spri, LPWRAP_PRI_READY)) {
return -1;
}
//if (!zap_test_flag(spri, LPWRAP_PRI_READY)) {
//return -1;
//}
FD_ZERO(&rfds);
FD_ZERO(&efds);
@ -246,9 +251,9 @@ int lpwrap_one_loop(struct lpwrap_pri *spri)
}
}
if (zap_test_flag(spri, LPWRAP_PRI_READY)) {
return sel;
}
return sel;
if ((handler = spri->eventmap[LPWRAP_PRI_EVENT_IO_FAIL] ? spri->eventmap[LPWRAP_PRI_EVENT_IO_FAIL] : spri->eventmap[0] ? spri->eventmap[0] : NULL)) {
handler(spri, LPWRAP_PRI_EVENT_IO_FAIL, NULL);

View File

@ -691,16 +691,103 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
return ret;
}
static __inline__ zap_status_t process_event(zap_span_t *span, zap_event_t *event)
{
zap_sigmsg_t sig;
zap_libpri_data_t *isdn_data = span->signal_data;
memset(&sig, 0, sizeof(sig));
sig.chan_id = event->channel->chan_id;
sig.span_id = event->channel->span_id;
sig.channel = event->channel;
zap_log(ZAP_LOG_DEBUG, "EVENT [%s][%d][%d:%d] STATE [%s]\n",
zap_oob_event2str(event->enum_id), event->enum_id, event->channel->span_id, event->channel->chan_id, zap_channel_state2str(event->channel->state));
switch(event->enum_id) {
case ZAP_OOB_ALARM_TRAP:
{
sig.event_id = ZAP_OOB_ALARM_TRAP;
if (event->channel->state != ZAP_CHANNEL_STATE_DOWN) {
if (event->channel->type == ZAP_CHAN_TYPE_B) {
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_RESTART);
}
}
zap_set_flag(event->channel, ZAP_CHANNEL_SUSPENDED);
zap_channel_get_alarms(event->channel);
isdn_data->sig_cb(&sig);
zap_log(ZAP_LOG_WARNING, "channel %d:%d (%d:%d) has alarms! [%s]\n",
event->channel->span_id, event->channel->chan_id,
event->channel->physical_span_id, event->channel->physical_chan_id,
event->channel->last_error);
}
break;
case ZAP_OOB_ALARM_CLEAR:
{
zap_log(ZAP_LOG_WARNING, "channel %d:%d (%d:%d) alarms Cleared!\n", event->channel->span_id, event->channel->chan_id,
event->channel->physical_span_id, event->channel->physical_chan_id);
sig.event_id = ZAP_OOB_ALARM_CLEAR;
zap_clear_flag(event->channel, ZAP_CHANNEL_SUSPENDED);
zap_channel_get_alarms(event->channel);
isdn_data->sig_cb(&sig);
}
break;
}
return ZAP_SUCCESS;
}
static __inline__ void check_events(zap_span_t *span)
{
zap_status_t status;
status = zap_span_poll_event(span, 5);
switch(status) {
case ZAP_SUCCESS:
{
zap_event_t *event;
while (zap_span_next_event(span, &event) == ZAP_SUCCESS) {
if (event->enum_id == ZAP_OOB_NOOP) {
continue;
}
if (process_event(span, event) != ZAP_SUCCESS) {
break;
}
}
}
break;
case ZAP_FAIL:
{
zap_log(ZAP_LOG_DEBUG, "Event Failure! %d\n", zap_running());
}
break;
default:
break;
}
}
static int check_flags(lpwrap_pri_t *spri)
{
zap_span_t *span = spri->private_info;
check_state(span);
if (!zap_running() || zap_test_flag(span, ZAP_SPAN_STOP_THREAD)) {
return -1;
}
check_state(span);
check_events(span);
return 0;
}
@ -769,27 +856,29 @@ static void *zap_libpri_run(zap_thread_t *me, void *obj)
{
zap_span_t *span = (zap_span_t *) obj;
zap_libpri_data_t *isdn_data = span->signal_data;
int x, i;
int i, x = 0;
int down = 0;
int got_d = 0;
zap_set_flag(span, ZAP_SPAN_IN_THREAD);
while(zap_running() && !zap_test_flag(span, ZAP_SPAN_STOP_THREAD)) {
x = 0;
for(i = 1; i <= span->chan_count; i++) {
if (span->channels[i]->type == ZAP_CHAN_TYPE_DQ921) {
if (zap_channel_open(span->span_id, i, &isdn_data->dchan) == ZAP_SUCCESS) {
zap_log(ZAP_LOG_DEBUG, "opening d-channel #%d %d:%d\n", x, isdn_data->dchan->span_id, isdn_data->dchan->chan_id);
isdn_data->dchan->state = ZAP_CHANNEL_STATE_UP;
x++;
break;
if (!got_d) {
for(i = 1; i <= span->chan_count; i++) {
if (span->channels[i]->type == ZAP_CHAN_TYPE_DQ921) {
if (zap_channel_open(span->span_id, i, &isdn_data->dchan) == ZAP_SUCCESS) {
zap_log(ZAP_LOG_DEBUG, "opening d-channel #%d %d:%d\n", x, isdn_data->dchan->span_id, isdn_data->dchan->chan_id);
isdn_data->dchan->state = ZAP_CHANNEL_STATE_UP;
got_d = 1;
x++;
break;
}
}
}
}
if (!x || lpwrap_init_pri(&isdn_data->spri,
if (lpwrap_init_pri(&isdn_data->spri,
span, // span
isdn_data->dchan, // dchan
isdn_data->pswitch,
@ -820,9 +909,8 @@ static void *zap_libpri_run(zap_thread_t *me, void *obj)
isdn_data->spri.on_loop = check_flags;
isdn_data->spri.private_info = span;
lpwrap_run_pri(&isdn_data->spri);
zap_channel_close(&isdn_data->dchan);
}
if (!zap_running() || zap_test_flag(span, ZAP_SPAN_STOP_THREAD)) {
@ -830,9 +918,15 @@ static void *zap_libpri_run(zap_thread_t *me, void *obj)
}
zap_log(ZAP_LOG_CRIT, "PRI down on span %d\n", isdn_data->spri.span->span_id);
zap_set_state_all(span, ZAP_CHANNEL_STATE_RESTART);
check_state(span);
if (!down) {
zap_set_state_all(span, ZAP_CHANNEL_STATE_RESTART);
check_state(span);
}
check_state(span);
check_events(span);
down++;
zap_sleep(5000);
}

View File

@ -215,7 +215,11 @@ static ZIO_CHANNEL_REQUEST_FUNCTION(ss7_boost_channel_request)
ss7bc_call_init(&event, caller_data->cid_num.digits, caller_data->ani.digits, r);
zap_set_string(event.calling_name, caller_data->cid_name);
zap_set_string(event.redirection_string, caller_data->rdnis.digits);
zap_set_string(event.isup_in_rdnis, caller_data->rdnis.digits);
if (strlen(caller_data->rdnis.digits)) {
event.isup_in_rdnis_size = strlen(caller_data->rdnis.digits)+1;
}
event.calling_number_screening_ind = caller_data->screen;
event.calling_number_presentation = caller_data->pres;
@ -483,7 +487,7 @@ static void handle_call_start(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_
}
zap_set_string(zchan->caller_data.ani.digits, (char *)event->calling_number_digits);
zap_set_string(zchan->caller_data.dnis.digits, (char *)event->called_number_digits);
zap_set_string(zchan->caller_data.rdnis.digits, (char *)event->redirection_string);
zap_set_string(zchan->caller_data.rdnis.digits, (char *)event->isup_in_rdnis);
zchan->caller_data.screen = event->calling_number_screening_ind;
zchan->caller_data.pres = event->calling_number_presentation;
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_RING);
@ -851,7 +855,7 @@ static void *zap_ss7_boost_run(zap_thread_t *me, void *obj)
zap_span_t *span = (zap_span_t *) obj;
zap_ss7_boost_data_t *ss7_boost_data = span->signal_data;
ss7bc_connection_t *mcon, *pcon;
uint32_t ms = 10, too_long = 20000;
uint32_t ms = 10; //, too_long = 20000;
ss7_boost_data->pcon = ss7_boost_data->mcon;
@ -942,6 +946,8 @@ static void *zap_ss7_boost_run(zap_thread_t *me, void *obj)
pcon->hb_elapsed = 0;
}
#if 0
if (pcon->hb_elapsed >= too_long) {
zap_log(ZAP_LOG_CRIT, "Lost Heartbeat!\n");
zap_set_flag_locked(span, ZAP_SPAN_SUSPENDED);
@ -953,6 +959,7 @@ static void *zap_ss7_boost_run(zap_thread_t *me, void *obj)
SIGBOOST_EVENT_SYSTEM_RESTART,
0);
}
#endif
if (zap_running()) {
check_state(span);
@ -1094,7 +1101,7 @@ static ZIO_SIG_CONFIGURE_FUNCTION(zap_ss7_boost_configure_span)
{
zap_ss7_boost_data_t *ss7_boost_data = NULL;
const char *local_ip = "127.0.0.65", *remote_ip = "127.0.0.66";
int local_port = 5300, remote_port = 5300;
int local_port = 53000, remote_port = 53000;
char *var, *val;
int *intval;

View File

@ -1,5 +1,5 @@
/****************************************************************************
* sigboost.h $Revision: 1.5 $
* sigboost.h $Revision: 1.13 $
*
* Definitions for the sigboost interface.
*
@ -14,6 +14,8 @@
#ifndef _SIGBOOST_H_
#define _SIGBOOST_H_
#define SIGBOOST_VERSION 100
#include <stdint.h>
#include <sys/time.h>
@ -48,14 +50,22 @@ enum e_sigboost_release_cause_values
enum e_sigboost_call_setup_ack_nack_cause_values
{
SIGBOOST_CALL_SETUP_NACK_ALL_CKTS_BUSY = 117, /* unused Q.850 value */
SIGBOOST_CALL_SETUP_NACK_TEST_CKT_BUSY = 118, /* unused Q.850 value */
SIGBOOST_CALL_SETUP_NACK_INVALID_NUMBER = 28,
/* probable elimination */
//SIGBOOST_CALL_SETUP_RESERVED = 0x00,
//SIGBOOST_CALL_SETUP_CIRCUIT_RESET = 0x10,
//SIGBOOST_CALL_SETUP_NACK_CKT_START_TIMEOUT = 0x11,
//SIGBOOST_CALL_SETUP_NACK_AUTO_CALL_GAP = 0x17,
//SIGBOOST_CALL_SETUP_NACK_ALL_CKTS_BUSY = 34, /* Q.850 value - don't use */
SIGBOOST_CALL_SETUP_NACK_ALL_CKTS_BUSY = 117, /* non Q.850 value indicates local all ckt busy
causing sangoma_mgd to perform automatic call
gapping*/
SIGBOOST_CALL_SETUP_NACK_TEST_CKT_BUSY = 17, /* Q.850 value */
SIGBOOST_CALL_SETUP_NACK_INVALID_NUMBER = 28, /* Q.850 value */
SIGBOOST_CALL_SETUP_CSUPID_DBL_USE = 200, /* unused Q.850 value */
};
enum e_sigboost_huntgroup_values
{
SIGBOOST_HUNTGRP_SEQ_ASC = 0x00, /* sequential with lowest available first */
SIGBOOST_HUNTGRP_SEQ_DESC = 0x01, /* sequential with highest available first */
SIGBOOST_HUNTGRP_RR_ASC = 0x02, /* round-robin with lowest available first */
SIGBOOST_HUNTGRP_RR_DESC = 0x03, /* round-robin with highest available first */
};
#define MAX_DIALED_DIGITS 31
@ -67,63 +77,73 @@ enum e_sigboost_call_setup_ack_nack_cause_values
#define CORE_MAX_CHAN_PER_SPAN 30
#define MAX_PENDING_CALLS CORE_MAX_SPANS * CORE_MAX_CHAN_PER_SPAN
/* 0..(MAX_PENDING_CALLS-1) is range of call_setup_id below */
#define SIZE_RDNIS 128
#define SIZE_RDNIS 900
#pragma pack(1)
typedef struct
{
uint32_t event_id;
uint8_t capability;
uint8_t uil1p;
}t_sigboost_bearer;
typedef struct
{
uint16_t version;
uint32_t event_id;
/* delete sequence numbers - SCTP does not need them */
uint32_t fseqno;
uint32_t bseqno;
uint16_t call_setup_id;
uint32_t trunk_group;
uint8_t span;
uint8_t chan;
struct timeval tv;
uint8_t called_number_digits_count;
char called_number_digits [MAX_DIALED_DIGITS + 1]; /* it's a null terminated string */
uint8_t calling_number_digits_count; /* it's an array */
char calling_number_digits [MAX_DIALED_DIGITS + 1]; /* it's a null terminated string */
uint32_t fseqno;
uint32_t bseqno;
uint16_t call_setup_id;
uint32_t trunk_group;
uint8_t span;
uint8_t chan;
struct timeval tv;
uint8_t called_number_digits_count;
char called_number_digits [MAX_DIALED_DIGITS + 1]; /* it's a null terminated string */
uint8_t calling_number_digits_count; /* it's an array */
char calling_number_digits [MAX_DIALED_DIGITS + 1]; /* it's a null terminated string */
/* ref. Q.931 Table 4-11 and Q.951 Section 3 */
uint8_t calling_number_screening_ind;
uint8_t calling_number_presentation;
char calling_name[MAX_DIALED_DIGITS + 1];
uint16_t redirection_string_size;
char redirection_string [SIZE_RDNIS]; /* it's a null terminated string */
/* redir string format:
* http://www.ss7box.com/wiki/tiki-index.php?page=Call+Redirection
* */
uint8_t calling_number_screening_ind;
uint8_t calling_number_presentation;
char calling_name[MAX_DIALED_DIGITS + 1];
t_sigboost_bearer bearer;
uint8_t hunt_group;
uint16_t isup_in_rdnis_size;
char isup_in_rdnis [SIZE_RDNIS]; /* it's a null terminated string */
} t_sigboost_callstart;
#define MIN_SIZE_CALLSTART_MSG (sizeof(t_sigboost_callstart) - SIZE_RDNIS)
#define MIN_SIZE_CALLSTART_MSG sizeof(t_sigboost_callstart) - SIZE_RDNIS
typedef struct
{
uint32_t event_id;
uint16_t version;
uint32_t event_id;
/* delete sequence numbers - SCTP does not need them */
uint32_t fseqno;
uint32_t bseqno;
uint16_t call_setup_id;
uint32_t trunk_group;
uint8_t span;
uint8_t chan;
struct timeval tv;
uint8_t release_cause;
uint32_t fseqno;
uint32_t bseqno;
uint16_t call_setup_id;
uint32_t trunk_group;
uint8_t span;
uint8_t chan;
struct timeval tv;
uint8_t release_cause;
} t_sigboost_short;
#pragma pack()
static inline int boost_full_event(int event_id)
{
switch (event_id) {
case SIGBOOST_EVENT_CALL_START:
case SIGBOOST_EVENT_DIGIT_IN:
return 1;
default:
return 0;
}
switch (event_id) {
case SIGBOOST_EVENT_CALL_START:
case SIGBOOST_EVENT_DIGIT_IN:
return 1;
default:
return 0;
}
return 0;
return 0;
}
#endif

View File

@ -73,7 +73,7 @@ static void ss7bc_print_event_call(ss7bc_connection_t *mcon, ss7bc_event_t *even
{
if (event->event_id == SIGBOOST_EVENT_HEARTBEAT)
return;
zap_log(file, func, line, ZAP_LOG_LEVEL_DEBUG, "%s EVENT: %s:(%X) [w%dg%d] CSid=%i Seq=%i Cn=[%s] Cd=[%s] Ci=[%s]\n",
zap_log(file, func, line, ZAP_LOG_LEVEL_WARNING, "%s EVENT: %s:(%X) [w%dg%d] CSid=%i Seq=%i Cn=[%s] Cd=[%s] Ci=[%s]\n",
dir ? "TX":"RX",
ss7bc_event_id_name(event->event_id),
event->event_id,
@ -91,7 +91,7 @@ static void ss7bc_print_event_short(ss7bc_connection_t *mcon, ss7bc_short_event_
{
if (event->event_id == SIGBOOST_EVENT_HEARTBEAT)
return;
zap_log(file, func, line, ZAP_LOG_LEVEL_DEBUG, "%s EVENT (%s): %s:(%X) [w%dg%d] Rc=%i CSid=%i Seq=%i \n",
zap_log(file, func, line, ZAP_LOG_LEVEL_WARNING, "%s EVENT (%s): %s:(%X) [w%dg%d] Rc=%i CSid=%i Seq=%i \n",
dir ? "TX":"RX",
priority ? "P":"N",
ss7bc_event_id_name(event->event_id),
@ -261,6 +261,10 @@ ss7bc_event_t *__ss7bc_connection_read(ss7bc_connection_t *mcon, int iteration,
bytes = recvfrom(mcon->socket, &mcon->event, sizeof(mcon->event), MSG_DONTWAIT,
(struct sockaddr *) &mcon->local_addr, &fromlen);
if (mcon->event.version != SIGBOOST_VERSION) {
zap_log(ZAP_LOG_CRIT, "Invalid Boost Version %i Expecting %i\n",mcon->event.version, SIGBOOST_VERSION);
}
/* Must check for < 0 cannot rely on bytes > MIN_SIZE_... compiler issue */
if (bytes < 0) {
msg_ok=0;
@ -293,7 +297,7 @@ ss7bc_event_t *__ss7bc_connection_read(ss7bc_connection_t *mcon, int iteration,
ss7bc_print_event_short(mcon, (ss7bc_short_event_t*)&mcon->event, 0, 0, file, func, line);
}
#if 1
#if 0
/* NC: NOT USED ANY MORE */
if (mcon->rxseq_reset) {
//if (mcon->event.event_id == SIGBOOST_EVENT_SYSTEM_RESTART_ACK) {
@ -310,15 +314,17 @@ ss7bc_event_t *__ss7bc_connection_read(ss7bc_connection_t *mcon, int iteration,
mcon->txwindow = mcon->txseq - mcon->event.bseqno;
mcon->rxseq++;
#if 0
if (mcon->rxseq != mcon->event.fseqno) {
zap_log(ZAP_LOG_CRIT, "Invalid Sequence Number Expect=%i Rx=%i\n", mcon->rxseq, mcon->event.fseqno);
return NULL;
}
#endif
return &mcon->event;
} else {
if (iteration == 0) {
zap_log(ZAP_LOG_CRIT, "Invalid Event length from boost rxlen=%i evsz=%i\n", bytes, sizeof(mcon->event));
zap_log(ZAP_LOG_CRIT, "NC - Invalid Event length from boost rxlen=%i evsz=%i\n", bytes, sizeof(mcon->event));
return NULL;
}
}
@ -332,6 +338,10 @@ ss7bc_event_t *__ss7bc_connection_readp(ss7bc_connection_t *mcon, int iteration,
int bytes = 0;
bytes = recvfrom(mcon->socket, &mcon->event, sizeof(mcon->event), MSG_DONTWAIT, (struct sockaddr *) &mcon->local_addr, &fromlen);
if (mcon->event.version != SIGBOOST_VERSION) {
zap_log(ZAP_LOG_CRIT, "Invalid Boost Version %i Expecting %i\n",mcon->event.version, SIGBOOST_VERSION);
}
if (bytes == sizeof(ss7bc_short_event_t)) {
@ -356,7 +366,7 @@ ss7bc_event_t *__ss7bc_connection_readp(ss7bc_connection_t *mcon, int iteration,
int __ss7bc_connection_write(ss7bc_connection_t *mcon, ss7bc_event_t *event, const char *file, const char *func, int line)
{
int err;
int event_size=sizeof(ss7bc_event_t);
int event_size=MIN_SIZE_CALLSTART_MSG+event->isup_in_rdnis_size;
if (!event || mcon->socket < 0 || !mcon->mutex) {
zap_log(file, func, line, ZAP_LOG_LEVEL_CRIT, "Critical Error: No Event Device\n");
@ -395,6 +405,7 @@ int __ss7bc_connection_write(ss7bc_connection_t *mcon, ss7bc_event_t *event, con
event->fseqno = mcon->txseq++;
}
event->bseqno = mcon->rxseq;
event->version = SIGBOOST_VERSION;
err = sendto(mcon->socket, event, event_size, 0, (struct sockaddr *) &mcon->remote_addr, sizeof(mcon->remote_addr));
zap_mutex_unlock(mcon->mutex);
@ -432,6 +443,7 @@ int __ss7bc_connection_writep(ss7bc_connection_t *mcon, ss7bc_event_t *event, co
gettimeofday(&event->tv, NULL);
zap_mutex_lock(mcon->mutex);
event->version = SIGBOOST_VERSION;
err = sendto(mcon->socket, event, event_size, 0, (struct sockaddr *) &mcon->remote_addr, sizeof(mcon->remote_addr));
zap_mutex_unlock(mcon->mutex);

View File

@ -38,7 +38,7 @@
#include "openzap.h"
#include <poll.h>
#include <sys/socket.h>
#include "wanpipe_tdm_api_iface.h"
#include "libsangoma.h"
typedef enum {
WP_RINGING = (1 << 0)
@ -57,196 +57,28 @@ static struct {
ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event);
ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event);
#define WP_INVALID_SOCKET -1
/* on windows right now, there is no way to specify if we want to read events here or not, we allways get them here */
/* we need some what to select if we are reading regular tdm msgs or events */
/* need to either have 2 functions, 1 for events, 1 for regural read, or a flag on this function to choose */
/* 2 functions preferred. Need implementation for the event function for both nix and windows that is threadsafe */
static __inline__ int tdmv_api_readmsg_tdm(sng_fd_t fd, void *hdrbuf, int hdrlen, void *databuf, int datalen)
{
/* What do we need to do here to avoid having to do all */
/* the memcpy's on windows and still maintain api compat with nix */
uint32_t rx_len=0;
#if defined(__WINDOWS__)
static RX_DATA_STRUCT rx_data;
api_header_t *pri;
wp_tdm_api_rx_hdr_t *tdm_api_rx_hdr;
wp_tdm_api_rx_hdr_t *user_buf = (wp_tdm_api_rx_hdr_t*)hdrbuf;
DWORD ln;
if (hdrlen != sizeof(wp_tdm_api_rx_hdr_t)){
return -1;
}
if (!DeviceIoControl(
fd,
IoctlReadCommand,
(LPVOID)NULL,
0L,
(LPVOID)&rx_data,
sizeof(RX_DATA_STRUCT),
(LPDWORD)(&ln),
(LPOVERLAPPED)NULL
)){
return -1;
}
pri = &rx_data.api_header;
tdm_api_rx_hdr = (wp_tdm_api_rx_hdr_t*)rx_data.data;
user_buf->wp_tdm_api_event_type = pri->operation_status;
switch(pri->operation_status)
{
case SANG_STATUS_RX_DATA_AVAILABLE:
if (pri->data_length > datalen){
break;
}
memcpy(databuf, rx_data.data, pri->data_length);
rx_len = pri->data_length;
break;
default:
break;
}
#else
struct msghdr msg;
struct iovec iov[2];
memset(&msg,0,sizeof(struct msghdr));
iov[0].iov_len=hdrlen;
iov[0].iov_base=hdrbuf;
iov[1].iov_len=datalen;
iov[1].iov_base=databuf;
msg.msg_iovlen=2;
msg.msg_iov=iov;
rx_len = read(fd,&msg,datalen+hdrlen);
if (rx_len <= sizeof(wp_tdm_api_rx_hdr_t)){
return -EINVAL;
}
rx_len-=sizeof(wp_tdm_api_rx_hdr_t);
#endif
return rx_len;
}
static __inline__ int tdmv_api_writemsg_tdm(sng_fd_t fd, void *hdrbuf, int hdrlen, void *databuf, unsigned short datalen)
{
/* What do we need to do here to avoid having to do all */
/* the memcpy's on windows and still maintain api compat with nix */
int bsent = 0;
#if defined(__WINDOWS__)
static TX_DATA_STRUCT local_tx_data;
api_header_t *pri;
DWORD ln;
/* Are these really not needed or used??? What about for nix?? */
(void)hdrbuf;
(void)hdrlen;
pri = &local_tx_data.api_header;
pri->data_length = datalen;
memcpy(local_tx_data.data, databuf, pri->data_length);
if (!DeviceIoControl(
fd,
IoctlWriteCommand,
(LPVOID)&local_tx_data,
(ULONG)sizeof(TX_DATA_STRUCT),
(LPVOID)&local_tx_data,
sizeof(TX_DATA_STRUCT),
(LPDWORD)(&ln),
(LPOVERLAPPED)NULL
)){
return -1;
}
if (local_tx_data.api_header.operation_status == SANG_STATUS_SUCCESS) {
bsent = datalen;
}
#else
struct msghdr msg;
struct iovec iov[2];
memset(&msg,0,sizeof(struct msghdr));
iov[0].iov_len = hdrlen;
iov[0].iov_base = hdrbuf;
iov[1].iov_len = datalen;
iov[1].iov_base = databuf;
msg.msg_iovlen = 2;
msg.msg_iov = iov;
bsent = write(fd, &msg, datalen + hdrlen);
if (bsent > 0){
bsent -= sizeof(wp_tdm_api_tx_hdr_t);
}
#endif
return bsent;
}
#define WP_INVALID_SOCKET -1
/* a cross platform way to poll on an actual pollset (span and/or list of spans) will probably also be needed for analog */
/* so we can have one analong handler thread that will deal with all the idle analog channels for events */
/* the alternative would be for the driver to provide one socket for all of the oob events for all analog channels */
static __inline__ int tdmv_api_wait_socket(sng_fd_t fd, int timeout, int *flags)
{
#if defined(__WINDOWS__)
DWORD ln;
API_POLL_STRUCT api_poll;
memset(&api_poll, 0x00, sizeof(API_POLL_STRUCT));
api_poll.user_flags_bitmap = *flags;
api_poll.timeout = timeout;
#ifdef LIBSANGOMA_VERSION
int err;
sangoma_wait_obj_t sangoma_wait_obj;
if (!DeviceIoControl(
fd,
IoctlApiPoll,
(LPVOID)NULL,
0L,
(LPVOID)&api_poll,
sizeof(API_POLL_STRUCT),
(LPDWORD)(&ln),
(LPOVERLAPPED)NULL)) {
return -1;
sangoma_init_wait_obj(&sangoma_wait_obj, fd, 1, 1, *flags, SANGOMA_WAIT_OBJ);
err=sangoma_socket_waitfor_many(&sangoma_wait_obj,1 , timeout);
if (err > 0) {
*flags=sangoma_wait_obj.flags_out;
}
return err;
*flags = 0;
switch(api_poll.operation_status)
{
case SANG_STATUS_RX_DATA_AVAILABLE:
break;
case SANG_STATUS_RX_DATA_TIMEOUT:
return 0;
default:
return -1;
}
if (api_poll.poll_events_bitmap == 0){
return -1;
}
if (api_poll.poll_events_bitmap & POLL_EVENT_TIMEOUT) {
return 0;
}
*flags = api_poll.poll_events_bitmap;
return 1;
#else
struct pollfd pfds[1];
struct pollfd pfds[1];
int res;
memset(&pfds[0], 0, sizeof(pfds[0]));
@ -265,87 +97,18 @@ static __inline__ int tdmv_api_wait_socket(sng_fd_t fd, int timeout, int *flags)
return res;
#endif
}
#define FNAME_LEN 128
static __inline__ sng_fd_t tdmv_api_open_span_chan(int span, int chan)
{
char fname[FNAME_LEN];
sng_fd_t fd = WP_INVALID_SOCKET;
#if defined(__WINDOWS__)
DWORD ln;
wan_udp_hdr_t wan_udp;
/* NOTE: under Windows Interfaces are zero based but 'chan' is 1 based. */
/* Subtract 1 from 'chan'. */
_snprintf(fname , FNAME_LEN, "\\\\.\\WANPIPE%d_IF%d", span, chan - 1);
fd = CreateFile( fname,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
(HANDLE)NULL
);
/* make sure that we are the only ones who have this chan open */
/* is this a threadsafe way to make sure that we are ok and will */
/* never return a valid handle to more than one thread for the same channel? */
wan_udp.wan_udphdr_command = GET_OPEN_HANDLES_COUNTER;
wan_udp.wan_udphdr_data_len = 0;
DeviceIoControl(
fd,
IoctlManagementCommand,
(LPVOID)&wan_udp,
sizeof(wan_udp_hdr_t),
(LPVOID)&wan_udp,
sizeof(wan_udp_hdr_t),
(LPDWORD)(&ln),
(LPOVERLAPPED)NULL
);
if ((wan_udp.wan_udphdr_return_code) || (*(int*)&wan_udp.wan_udphdr_data[0] != 1)){
/* somone already has this channel, or somthing else is not right. */
tdmv_api_close_socket(&fd);
}
#else
/* Does this fail if another thread already has this chan open? */
/* if not, we need to add some code to make sure it does */
snprintf(fname, FNAME_LEN, "/dev/wptdm_s%dc%d",span,chan);
fd = open(fname, O_RDWR);
if (fd < 0) {
fd = WP_INVALID_SOCKET;
}
#endif
return fd;
return sangoma_open_tdmapi_span_chan(span, chan);
}
static zap_io_interface_t wanpipe_interface;
static zap_status_t wp_tdm_cmd_exec(zap_channel_t *zchan, wanpipe_tdm_api_t *tdm_api)
{
int err;
/* I'm told the 2nd arg is ignored but i send it as the cmd anyway for good measure */
err = ioctl(zchan->sockfd, tdm_api->wp_tdm_cmd.cmd, &tdm_api->wp_tdm_cmd);
if (err) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "%s", strerror(errno));
return ZAP_FAIL;
}
return ZAP_SUCCESS;
}
static unsigned char wanpipe_swap_bits(unsigned char cas_bits)
{
unsigned char swapped_bits = 0x0;
@ -374,59 +137,60 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
for(x = start; x < end; x++) {
zap_channel_t *chan;
zap_socket_t sockfd = WP_INVALID_SOCKET;
const char *dtmf = "none";
sockfd = tdmv_api_open_span_chan(spanno, x);
if (sockfd != WP_INVALID_SOCKET && zap_span_add_channel(span, sockfd, type, &chan) == ZAP_SUCCESS) {
wanpipe_tdm_api_t tdm_api;
zap_log(ZAP_LOG_INFO, "configuring device s%dc%d as OpenZAP device %d:%d fd:%d\n", spanno, x, chan->span_id, chan->chan_id, sockfd);
memset(&tdm_api,0,sizeof(tdm_api));
chan->physical_span_id = spanno;
chan->physical_chan_id = x;
chan->rate = 8000;
if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO) {
#if 1
if (type == ZAP_CHAN_TYPE_FXO) {
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_ONHOOK;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
wp_tdm_cmd_exec(chan, &tdm_api);
}
#endif
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_RING_DETECT;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
wp_tdm_cmd_exec(chan, &tdm_api);
#if 1
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_RING_TRIP_DETECT;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
wp_tdm_cmd_exec(chan, &tdm_api);
#endif
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_RXHOOK;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
wp_tdm_cmd_exec(chan, &tdm_api);
}
if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO || type == ZAP_CHAN_TYPE_B) {
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_GET_HW_CODING;
wp_tdm_cmd_exec(chan, &tdm_api);
int err;
dtmf = "software";
/* FIXME: Handle Error Conditino Check for return code */
err= sangoma_tdm_get_hw_coding(chan->sockfd, &tdm_api);
if (tdm_api.wp_tdm_cmd.hw_tdm_coding) {
chan->native_codec = chan->effective_codec = ZAP_CODEC_ALAW;
} else {
chan->native_codec = chan->effective_codec = ZAP_CODEC_ULAW;
}
err = sangoma_tdm_get_hw_dtmf(chan->sockfd, &tdm_api);
if (err > 0) {
err = sangoma_tdm_enable_dtmf_events(chan->sockfd, &tdm_api);
if (err == 0) {
zap_channel_set_feature(chan, ZAP_CHANNEL_FEATURE_DTMF_DETECT);
dtmf = "hardware";
}
}
}
#if 0
if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO) {
/* Enable FLASH/Wink Events */
int err=sangoma_set_rm_rxflashtime(chan->sockfd, &tdm_api, wp_globals.flash_ms);
if (err == 0) {
zap_log(ZAP_LOG_ERROR, "flash enabled s%dc%d\n", spanno, x);
} else {
zap_log(ZAP_LOG_ERROR, "flash disabled s%dc%d\n", spanno, x);
}
}
#endif
if (type == ZAP_CHAN_TYPE_CAS) {
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_WRITE_RBS_BITS;
tdm_api.wp_tdm_cmd.rbs_tx_bits = wanpipe_swap_bits(cas_bits);
wp_tdm_cmd_exec(chan, &tdm_api);
#ifdef LIBSANGOMA_VERSION
sangoma_tdm_write_rbs(chan->sockfd,&tdm_api,chan->physical_chan_id,wanpipe_swap_bits(cas_bits));
#else
sangoma_tdm_write_rbs(chan->sockfd,&tdm_api,wanpipe_swap_bits(cas_bits));
#endif
}
if (!zap_strlen_zero(name)) {
@ -439,6 +203,9 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
} else {
zap_log(ZAP_LOG_ERROR, "failure configuring device s%dc%d\n", spanno, x);
}
zap_log(ZAP_LOG_INFO, "configuring device s%dc%d as OpenZAP device %d:%d fd:%d DTMF: %s\n",
spanno, x, chan->span_id, chan->chan_id, sockfd, dtmf);
}
return configured;
@ -552,16 +319,15 @@ static ZIO_OPEN_FUNCTION(wanpipe_open)
wanpipe_tdm_api_t tdm_api;
memset(&tdm_api,0,sizeof(tdm_api));
if (zchan->type == ZAP_CHAN_TYPE_DQ921 || zchan->type == ZAP_CHAN_TYPE_DQ931) {
zchan->native_codec = zchan->effective_codec = ZAP_CODEC_NONE;
} else {
zchan->effective_codec = zchan->native_codec;
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_CODEC;
tdm_api.wp_tdm_cmd.tdm_codec = 0;
wp_tdm_cmd_exec(zchan, &tdm_api);
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_USR_PERIOD;
tdm_api.wp_tdm_cmd.usr_period = wp_globals.codec_ms;
wp_tdm_cmd_exec(zchan, &tdm_api);
sangoma_tdm_set_usr_period(zchan->sockfd, &tdm_api, wp_globals.codec_ms);
zap_channel_set_feature(zchan, ZAP_CHANNEL_FEATURE_INTERVAL);
zchan->effective_interval = zchan->native_interval = wp_globals.codec_ms;
zchan->packet_len = zchan->native_interval * 8;
@ -585,10 +351,8 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
switch(command) {
case ZAP_COMMAND_OFFHOOK:
{
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_OFFHOOK;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) {
err=sangoma_tdm_txsig_offhook(zchan->sockfd,&tdm_api);
if (err) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "OFFHOOK Failed");
return ZAP_FAIL;
}
@ -597,10 +361,8 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
break;
case ZAP_COMMAND_ONHOOK:
{
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_ONHOOK;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) {
err=sangoma_tdm_txsig_onhook(zchan->sockfd,&tdm_api);
if (err) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "ONHOOK Failed");
return ZAP_FAIL;
}
@ -609,9 +371,8 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
break;
case ZAP_COMMAND_GENERATE_RING_ON:
{
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_START;
if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) {
err=sangoma_tdm_txsig_start(zchan->sockfd,&tdm_api);
if (err) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring Failed");
return ZAP_FAIL;
}
@ -622,9 +383,8 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
break;
case ZAP_COMMAND_GENERATE_RING_OFF:
{
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_OFFHOOK;
if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) {
err=sangoma_tdm_txsig_offhook(zchan->sockfd,&tdm_api);
if (err) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring-off Failed");
return ZAP_FAIL;
}
@ -634,27 +394,26 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
break;
case ZAP_COMMAND_GET_INTERVAL:
{
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_GET_USR_PERIOD;
if (!(err = wp_tdm_cmd_exec(zchan, &tdm_api))) {
ZAP_COMMAND_OBJ_INT = tdm_api.wp_tdm_cmd.usr_period;
err=sangoma_tdm_get_usr_period(zchan->sockfd, &tdm_api);
if (err > 0 ) {
ZAP_COMMAND_OBJ_INT = err;
err=0;
}
}
break;
case ZAP_COMMAND_SET_INTERVAL:
{
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_USR_PERIOD;
tdm_api.wp_tdm_cmd.usr_period = ZAP_COMMAND_OBJ_INT;
err = wp_tdm_cmd_exec(zchan, &tdm_api);
err=sangoma_tdm_set_usr_period(zchan->sockfd, &tdm_api, ZAP_COMMAND_OBJ_INT);
zchan->packet_len = zchan->native_interval * (zchan->effective_codec == ZAP_CODEC_SLIN ? 16 : 8);
}
break;
case ZAP_COMMAND_SET_CAS_BITS:
{
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_WRITE_RBS_BITS;
tdm_api.wp_tdm_cmd.rbs_tx_bits = wanpipe_swap_bits(ZAP_COMMAND_OBJ_INT);
err = wp_tdm_cmd_exec(zchan, &tdm_api);
#ifdef LIBSANGOMA_VERSION
err=sangoma_tdm_write_rbs(zchan->sockfd,&tdm_api,zchan->physical_chan_id,wanpipe_swap_bits(ZAP_COMMAND_OBJ_INT));
#else
err=sangoma_tdm_write_rbs(zchan->sockfd,&tdm_api,wanpipe_swap_bits(ZAP_COMMAND_OBJ_INT));
#endif
}
break;
case ZAP_COMMAND_GET_CAS_BITS:
@ -683,14 +442,18 @@ static ZIO_READ_FUNCTION(wanpipe_read)
memset(&hdrframe, 0, sizeof(hdrframe));
rx_len = tdmv_api_readmsg_tdm(zchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (int)*datalen);
rx_len = sangoma_readmsg_tdm(zchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (int)*datalen,0);
*datalen = rx_len;
if (rx_len <= 0) {
if (rx_len == 0 || rx_len == -17) {
return ZAP_TIMEOUT;
}
if (rx_len < 0) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "%s", strerror(errno));
return ZAP_FAIL;
}
}
return ZAP_SUCCESS;
}
@ -702,7 +465,7 @@ static ZIO_WRITE_FUNCTION(wanpipe_write)
/* Do we even need the headerframe here? on windows, we don't even pass it to the driver */
memset(&hdrframe, 0, sizeof(hdrframe));
bsent = tdmv_api_writemsg_tdm(zchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (unsigned short)(*datalen));
bsent = sangoma_writemsg_tdm(zchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (unsigned short)(*datalen),0);
/* should we be checking if bsent == *datalen here? */
if (bsent > 0) {
@ -759,19 +522,29 @@ static ZIO_WAIT_FUNCTION(wanpipe_wait)
return ZAP_SUCCESS;
}
#ifndef WIN32
ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
{
#ifdef LIBSANGOMA_VERSION
sangoma_wait_obj_t pfds[ZAP_MAX_CHANNELS_SPAN];
#else
struct pollfd pfds[ZAP_MAX_CHANNELS_SPAN];
#endif
uint32_t i, j = 0, k = 0, l = 0;
int objects=0;
int r;
for(i = 1; i <= span->chan_count; i++) {
zap_channel_t *zchan = span->channels[i];
#ifdef LIBSANGOMA_VERSION
sangoma_init_wait_obj(&pfds[j], zchan->sockfd , 1, 1, POLLPRI, SANGOMA_WAIT_OBJ);
#else
memset(&pfds[j], 0, sizeof(pfds[j]));
pfds[j].fd = span->channels[i]->sockfd;
pfds[j].events = POLLPRI;
#endif
objects++;
/* The driver probably should be able to do this wink/flash/ringing by itself this is sort of a hack to make it work! */
if (zap_test_flag(zchan, ZAP_CHANNEL_WINK) || zap_test_flag(zchan, ZAP_CHANNEL_FLASH)) {
@ -789,20 +562,16 @@ ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
int err;
memset(&tdm_api, 0, sizeof(tdm_api));
if (zap_test_pflag(zchan, WP_RINGING)) {
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_OFFHOOK;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_DISABLE;
if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) {
err=sangoma_tdm_txsig_offhook(zchan->sockfd,&tdm_api);
if (err) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring-off Failed");
return ZAP_FAIL;
}
zap_clear_pflag_locked(zchan, WP_RINGING);
zchan->ring_time = zap_current_time_in_ms() + wp_globals.ring_off_ms;
} else {
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_START;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) {
err=sangoma_tdm_txsig_start(zchan->sockfd,&tdm_api);
if (err) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring Failed");
return ZAP_FAIL;
}
@ -815,8 +584,11 @@ ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
if (l) {
ms = l;
}
r = poll(pfds, j, ms);
#ifdef LIBSANGOMA_VERSION
r = sangoma_socket_waitfor_many(pfds,objects,ms);
#else
r = poll(pfds, j, ms);
#endif
if (r == 0) {
return l ? ZAP_SUCCESS : ZAP_TIMEOUT;
@ -828,7 +600,11 @@ ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
for(i = 1; i <= span->chan_count; i++) {
zap_channel_t *zchan = span->channels[i];
#ifdef LIBSANGOMA_VERSION
if (pfds[i-1].flags_out & POLLPRI) {
#else
if (pfds[i-1].revents & POLLPRI) {
#endif
zap_set_flag(zchan, ZAP_CHANNEL_EVENT);
zchan->last_event_time = zap_current_time_in_ms();
k++;
@ -836,15 +612,43 @@ ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
}
return k ? ZAP_SUCCESS : ZAP_FAIL;
}
static ZIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
{
wanpipe_tdm_api_t tdm_api;
unsigned int alarms = 0;
int err;
memset(&tdm_api,0,sizeof(tdm_api));
#ifdef LIBSANGOMA_VERSION
if ((err = sangoma_tdm_get_fe_alarms(zchan->sockfd, &tdm_api, &alarms))) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "ioctl failed (%s)", strerror(errno));
snprintf(zchan->span->last_error, sizeof(zchan->span->last_error), "ioctl failed (%s)", strerror(errno));
return ZAP_FAIL;
}
#else
if ((err = sangoma_tdm_get_fe_alarms(zchan->sockfd, &tdm_api)) < 0){
snprintf(zchan->last_error, sizeof(zchan->last_error), "ioctl failed (%s)", strerror(errno));
snprintf(zchan->span->last_error, sizeof(zchan->span->last_error), "ioctl failed (%s)", strerror(errno));
return ZAP_FAIL;
}
alarms = tdm_api.wp_tdm_cmd.fe_alarms;
#endif
zchan->alarm_flags = alarms ? ZAP_ALARM_RED : ZAP_ALARM_NONE;
return ZAP_SUCCESS;
}
ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
{
uint32_t i;
uint32_t i,err;
zap_oob_event_t event_id;
for(i = 1; i <= span->chan_count; i++) {
@ -869,29 +673,43 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
event_id = ZAP_OOB_ONHOOK;
if (span->channels[i]->type == ZAP_CHAN_TYPE_FXO) {
zap_channel_t *zchan = span->channels[i];
wanpipe_tdm_api_t tdm_api;
memset(&tdm_api, 0, sizeof(tdm_api));
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_ONHOOK;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
wp_tdm_cmd_exec(span->channels[i], &tdm_api);
sangoma_tdm_txsig_onhook(zchan->sockfd,&tdm_api);
}
goto event;
}
}
}
}
if (zap_test_flag(span->channels[i], ZAP_CHANNEL_EVENT)) {
wanpipe_tdm_api_t tdm_api;
zap_channel_t *zchan = span->channels[i];
memset(&tdm_api, 0, sizeof(tdm_api));
zap_clear_flag(span->channels[i], ZAP_CHANNEL_EVENT);
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_READ_EVENT;
if (wp_tdm_cmd_exec(span->channels[i], &tdm_api) != ZAP_SUCCESS) {
err=sangoma_tdm_read_event(zchan->sockfd,&tdm_api);
if (err != ZAP_SUCCESS) {
snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno));
return ZAP_FAIL;
}
switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type) {
case WP_TDMAPI_EVENT_LINK_STATUS:
{
switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_link_status) {
case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED:
event_id = ZAP_OOB_ALARM_CLEAR;
break;
default:
event_id = ZAP_OOB_ALARM_TRAP;
break;
};
}
break;
case WP_TDMAPI_EVENT_RXHOOK:
{
if (span->channels[i]->type == ZAP_CHAN_TYPE_FXS) {
@ -918,11 +736,9 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
continue;
} else {
int err;
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_ONHOOK;
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
if ((err = wp_tdm_cmd_exec(span->channels[i], &tdm_api))) {
zap_channel_t *zchan = span->channels[i];
err=sangoma_tdm_txsig_onhook(zchan->sockfd,&tdm_api);
if (err) {
snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "ONHOOK Failed");
return ZAP_FAIL;
}
@ -948,6 +764,20 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
span->channels[i]->cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits);
}
break;
case WP_TDMAPI_EVENT_DTMF:
{
char tmp_dtmf[2] = { tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_digit, 0 };
event_id = ZAP_OOB_NOOP;
//zap_log(ZAP_LOG_DEBUG, "%d:%d queue hardware dtmf %s\n", zchan->span_id, zchan->chan_id, tmp_dtmf);
if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_STOP) {
zap_channel_queue_dtmf(zchan, tmp_dtmf);
}
}
break;
case WP_TDMAPI_EVENT_ALARM:
event_id = ZAP_OOB_NOOP;
break;
default:
{
zap_log(ZAP_LOG_WARNING, "Unhandled event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type);
@ -1005,6 +835,7 @@ static ZIO_IO_LOAD_FUNCTION(wanpipe_init)
#endif
wanpipe_interface.next_event = wanpipe_next_event;
wanpipe_interface.channel_destroy = wanpipe_channel_destroy;
wanpipe_interface.get_alarms = wanpipe_get_alarms;
*zio = &wanpipe_interface;
return ZAP_SUCCESS;

View File

@ -868,6 +868,9 @@ static ZIO_READ_FUNCTION(zt_read)
if ((r = read(zchan->sockfd, data, *datalen)) > 0) {
break;
}
if (r == 0) {
errs--;
}
}
if (r > 0) {
@ -878,7 +881,7 @@ static ZIO_READ_FUNCTION(zt_read)
return ZAP_SUCCESS;
}
return ZAP_FAIL;
return r == 0 ? ZAP_TIMEOUT : ZAP_FAIL;
}
static ZIO_WRITE_FUNCTION(zt_write)