added initial OpenR2 support

git-svn-id: http://svn.openzap.org/svn/openzap/trunk@808 a93c3328-9c30-0410-af19-c9cd2b2d52af
This commit is contained in:
Moises Silva 2009-08-19 21:47:56 +00:00
parent b429cb1111
commit f7cd254439
11 changed files with 1899 additions and 45 deletions

View File

@ -101,7 +101,7 @@ core-install: install-libLTLIBRARIES
#
# tools & test programs
#
noinst_PROGRAMS = testtones detect_tones detect_dtmf testisdn testpri testboost testanalog testapp testcid
noinst_PROGRAMS = testtones detect_tones detect_dtmf testisdn testpri testr2 testboost testanalog testapp testcid
testapp_SOURCES = $(SRC)/testapp.c
testapp_LDADD = libopenzap.la
@ -131,6 +131,10 @@ testpri_SOURCES = $(SRC)/testpri.c
testpri_LDADD = libopenzap.la
testpri_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
testr2_SOURCES = $(SRC)/testr2.c
testr2_LDADD = libopenzap.la
testr2_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
testboost_SOURCES = $(SRC)/testboost.c
testboost_LDADD = libopenzap.la
testboost_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
@ -152,6 +156,10 @@ if LIBPRI
mod_LTLIBRARIES += ozmod_libpri.la
endif
if OPENR2
mod_LTLIBRARIES += ozmod_r2.la
endif
ozmod_zt_la_SOURCES = $(SRC)/ozmod/ozmod_zt/ozmod_zt.c
ozmod_zt_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
ozmod_zt_la_LDFLAGS = -module -avoid-version
@ -218,6 +226,13 @@ ozmod_libpri_la_LDFLAGS = -module -avoid-version -lpri
ozmod_libpri_la_LIBADD = $(MYLIB)
endif
if OPENR2
ozmod_r2_la_SOURCES = $(SRC)/ozmod/ozmod_r2/ozmod_r2.c
ozmod_r2_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
ozmod_r2_la_LDFLAGS = -module -avoid-version -lopenr2
ozmod_r2_la_LIBADD = $(MYLIB)
endif
dox doxygen:
cd docs && doxygen $(OZ_SRCDIR)/docs/Doxygen.conf

View File

@ -168,6 +168,9 @@ AM_CONDITIONAL([LIBSANGOMA],[test "${have_libsangoma}" = "yes"])
AM_CONDITIONAL([LIBPRI],[test "${enable_libpri}" = "yes"])
AC_CHECK_LIB([openr2], [openr2_context_set_io_type], [have_openr2="yes"])
AM_CONDITIONAL([OPENR2],[test "${have_openr2}" = "yes"])
COMP_VENDOR_CFLAGS="$COMP_VENDOR_CFLAGS"
AC_SUBST(COMP_VENDOR_CFLAGS)
AC_CONFIG_FILES([Makefile

View File

@ -24,6 +24,7 @@
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
* Moises Silva <moy@sangoma.com>
*
*
* mod_openzap.c -- OPENZAP Endpoint Module
@ -446,6 +447,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
switch (tech_pvt->zchan->type) {
case ZAP_CHAN_TYPE_FXO:
case ZAP_CHAN_TYPE_EM:
case ZAP_CHAN_TYPE_CAS:
{
zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_HANGUP);
@ -723,6 +725,65 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
}
static switch_status_t channel_receive_message_cas(switch_core_session_t *session, switch_core_session_message_t *msg)
{
switch_channel_t *channel;
private_t *tech_pvt;
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
tech_pvt = (private_t *) switch_core_session_get_private(session);
assert(tech_pvt != NULL);
zap_log(ZAP_LOG_DEBUG, "Got Freeswitch message in R2 channel %d [%d]\n", tech_pvt->zchan->physical_chan_id,
msg->message_id);
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_RINGING:
{
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
} else {
zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
}
}
break;
case SWITCH_MESSAGE_INDICATE_PROGRESS:
{
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_MEDIA);
} else {
zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS_MEDIA);
}
}
break;
case SWITCH_MESSAGE_INDICATE_ANSWER:
{
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED);
} else {
/* lets make the ozmod_r2 module life easier by moving thru each
* state waiting for completion, clumsy, but does the job
*/
if (tech_pvt->zchan->state < ZAP_CHANNEL_STATE_PROGRESS) {
zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
}
if (tech_pvt->zchan->state < ZAP_CHANNEL_STATE_PROGRESS_MEDIA) {
zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS_MEDIA);
}
zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_UP);
}
}
break;
default:
break;
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t channel_receive_message_b(switch_core_session_t *session, switch_core_session_message_t *msg)
{
@ -877,6 +938,9 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
case ZAP_CHAN_TYPE_B:
status = channel_receive_message_b(session, msg);
break;
case ZAP_CHAN_TYPE_CAS:
status = channel_receive_message_cas(session, msg);
break;
default:
status = SWITCH_STATUS_FALSE;
break;
@ -1473,6 +1537,106 @@ static ZIO_SIGNAL_CB_FUNCTION(on_fxs_signal)
return status;
}
static ZIO_SIGNAL_CB_FUNCTION(on_r2_signal)
{
switch_core_session_t *session = NULL;
switch_channel_t *channel = NULL;
zap_status_t status = ZAP_SUCCESS;
zap_log(ZAP_LOG_DEBUG, "Got R2 channel sig [%s] in channel %d\n", zap_signal_event2str(sigmsg->event_id), sigmsg->channel->physical_chan_id);
switch(sigmsg->event_id) {
/* on_call_disconnect from the R2 side */
case ZAP_SIGEVENT_STOP:
{
while((session = zap_channel_get_session(sigmsg->channel, 0))) {
channel = switch_core_session_get_channel(session);
switch_channel_hangup(channel, sigmsg->channel->caller_data.hangup_cause);
zap_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session));
switch_core_session_rwunlock(session);
}
}
break;
/* on_call_offered from the R2 side */
case ZAP_SIGEVENT_START:
{
status = zap_channel_from_event(sigmsg, &session);
}
break;
/* on DNIS received from the R2 forward side, return status == ZAP_BREAK to stop requesting DNIS */
case ZAP_SIGEVENT_COLLECTED_DIGIT:
{
char *regex = SPAN_CONFIG[sigmsg->channel->span->span_id].dial_regex;
char *fail_regex = SPAN_CONFIG[sigmsg->channel->span->span_id].fail_dial_regex;
if (switch_strlen_zero(regex)) {
regex = NULL;
}
if (switch_strlen_zero(fail_regex)) {
fail_regex = NULL;
}
zap_log(ZAP_LOG_DEBUG, "R2 DNIS so far [%s]\n", sigmsg->channel->caller_data.dnis.digits);
if ((regex || fail_regex) && !switch_strlen_zero(sigmsg->channel->caller_data.dnis.digits)) {
switch_regex_t *re = NULL;
int ovector[30];
int match = 0;
if (fail_regex) {
match = switch_regex_perform(sigmsg->channel->caller_data.dnis.digits, fail_regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0]));
status = match ? ZAP_SUCCESS : ZAP_BREAK;
switch_regex_safe_free(re);
}
if (status == ZAP_SUCCESS && regex) {
match = switch_regex_perform(sigmsg->channel->caller_data.dnis.digits, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0]));
status = match ? ZAP_BREAK : ZAP_SUCCESS;
}
switch_regex_safe_free(re);
}
}
break;
case ZAP_SIGEVENT_PROGRESS:
{
if ((session = zap_channel_get_session(sigmsg->channel, 0))) {
channel = switch_core_session_get_channel(session);
switch_channel_mark_ring_ready(channel);
switch_core_session_rwunlock(session);
}
}
break;
case ZAP_SIGEVENT_UP:
{
if ((session = zap_channel_get_session(sigmsg->channel, 0))) {
zap_tone_type_t tt = ZAP_TONE_DTMF;
channel = switch_core_session_get_channel(session);
switch_channel_mark_answered(channel);
if (zap_channel_command(sigmsg->channel, ZAP_COMMAND_ENABLE_DTMF_DETECT, &tt) != ZAP_SUCCESS) {
zap_log(ZAP_LOG_ERROR, "Failed to enable DTMF detection in R2 channel %d:%d\n", sigmsg->channel->span_id, sigmsg->channel->chan_id);
}
switch_core_session_rwunlock(session);
}
}
break;
default:
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled event %d from R2 for channel %d:%d\n",
sigmsg->event_id, sigmsg->channel->span_id, sigmsg->channel->chan_id);
}
break;
}
return status;
}
static ZIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
{
switch_core_session_t *session = NULL;
@ -2154,7 +2318,170 @@ static switch_status_t load_config(void)
}
}
if ((spans = switch_xml_child(cfg, "r2_spans"))) {
for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
char *id = (char *) switch_xml_attr(myspan, "id");
char *name = (char *) switch_xml_attr(myspan, "name");
zap_status_t zstatus = ZAP_FAIL;
/* strings */
const char *variant = "itu";
const char *category = "national_subscriber";
const char *logdir = "/usr/local/freeswitch/log/"; /* FIXME: get PREFIX variable */
const char *logging = "notice,warning,error";
const char *advanced_protocol_file = "";
/* booleans */
int call_files = 0;
int get_ani_first = -1;
int immediate_accept = -1;
int double_answer = -1;
int skip_category = -1;
int forced_release = -1;
int charge_calls = -1;
/* integers */
int mfback_timeout = -1;
int metering_pulse_timeout = -1;
int allow_collect_calls = -1;
int max_ani = 10;
int max_dnis = 4;
/* common non r2 stuff */
const char *context = "default";
const char *dialplan = "XML";
char *dial_regex = NULL;
char *fail_dial_regex = NULL;
uint32_t span_id = 0;
zap_span_t *span = NULL;
for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
/* string parameters */
if (!strcasecmp(var, "variant")) {
variant = val;
} else if (!strcasecmp(var, "category")) {
category = val;
} else if (!strcasecmp(var, "logdir")) {
logdir = val;
} else if (!strcasecmp(var, "logging")) {
logging = val;
} else if (!strcasecmp(var, "advanced_protocol_file")) {
advanced_protocol_file = val;
/* booleans */
} else if (!strcasecmp(var, "allow_collect_calls")) {
allow_collect_calls = switch_true(val);
} else if (!strcasecmp(var, "immediate_accept")) {
immediate_accept = switch_true(val);
} else if (!strcasecmp(var, "double_answer")) {
double_answer = switch_true(val);
} else if (!strcasecmp(var, "skip_category")) {
skip_category = switch_true(var);
} else if (!strcasecmp(var, "forced_release")) {
forced_release = switch_true(val);
} else if (!strcasecmp(var, "charge_calls")) {
charge_calls = switch_true(val);
} else if (!strcasecmp(var, "get_ani_first")) {
get_ani_first = switch_true(val);
} else if (!strcasecmp(var, "call_files")) {
call_files = switch_true(val);
/* integers */
} else if (!strcasecmp(var, "mfback_timeout")) {
mfback_timeout = atoi(val);
} else if (!strcasecmp(var, "metering_pulse_timeout")) {
metering_pulse_timeout = atoi(val);
} else if (!strcasecmp(var, "max_ani")) {
max_ani = atoi(val);
} else if (!strcasecmp(var, "max_dnis")) {
max_dnis = atoi(val);
/* common non r2 stuff */
} else if (!strcasecmp(var, "context")) {
context = val;
} else if (!strcasecmp(var, "dialplan")) {
dialplan = val;
} else if (!strcasecmp(var, "dial-regex")) {
dial_regex = val;
} else if (!strcasecmp(var, "fail-dial-regex")) {
fail_dial_regex = val;
}
}
if (!id && !name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n");
continue;
}
if (name) {
zstatus = zap_span_find_by_name(name, &span);
} else {
if (switch_is_number(id)) {
span_id = atoi(id);
zstatus = zap_span_find(span_id, &span);
}
if (zstatus != ZAP_SUCCESS) {
zstatus = zap_span_find_by_name(id, &span);
}
}
if (zstatus != ZAP_SUCCESS) {
zap_log(ZAP_LOG_ERROR, "Error finding OpenZAP span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
continue;
}
if (!span_id) {
span_id = span->span_id;
}
if (zap_configure_span("r2", span, on_r2_signal,
"variant", variant,
"max_ani", max_ani,
"max_dnis", max_dnis,
"category", category,
"logdir", logdir,
"logging", logging,
"advanced_protocol_file", advanced_protocol_file,
"allow_collect_calls", allow_collect_calls,
"immediate_accept", immediate_accept,
"double_answer", double_answer,
"skip_category", skip_category,
"forced_release", forced_release,
"charge_calls", charge_calls,
"get_ani_first", get_ani_first,
"call_files", call_files,
"mfback_timeout", mfback_timeout,
"metering_pulse_timeout", metering_pulse_timeout,
TAG_END) != ZAP_SUCCESS) {
zap_log(ZAP_LOG_ERROR, "Error configuring R2 OpenZAP span %d, error: %s\n",
span_id, span->last_error);
continue;
}
if (dial_regex) {
switch_set_string(SPAN_CONFIG[span->span_id].dial_regex, dial_regex);
}
if (fail_dial_regex) {
switch_set_string(SPAN_CONFIG[span->span_id].fail_dial_regex, fail_dial_regex);
}
SPAN_CONFIG[span->span_id].span = span;
switch_copy_string(SPAN_CONFIG[span->span_id].context, context, sizeof(SPAN_CONFIG[span->span_id].context));
switch_copy_string(SPAN_CONFIG[span->span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span->span_id].dialplan));
switch_copy_string(SPAN_CONFIG[span->span_id].type, "r2", sizeof(SPAN_CONFIG[span->span_id].type));
if (zap_span_start(span) == ZAP_FAIL) {
zap_log(ZAP_LOG_ERROR, "Error starting R2 OpenZAP span %d, error: %s\n", span_id, span->last_error);
continue;
}
}
}
switch_xml_free(xml);

View File

@ -280,6 +280,17 @@
} \
} while(0);
#define zap_locked_wait_for_flag_cleared(obj, flag, time) \
do { \
int __safety = time; \
while(__safety-- && zap_test_flag(obj, flag)) { \
zap_sleep(10); \
} \
if(!__safety) { \
zap_log(ZAP_LOG_CRIT, "flag %d was never cleared\n", flag); \
} \
} while(0);
typedef enum {
ZAP_STATE_CHANGE_FAIL,
@ -517,7 +528,7 @@ struct zap_channel {
struct zap_span *span;
struct zap_io_interface *zio;
zap_hash_t *variable_hash;
unsigned char cas_bits;
unsigned char rx_cas_bits;
};

View File

@ -175,7 +175,8 @@ typedef enum {
ZAP_SIGTYPE_RBS,
ZAP_SIGTYPE_ANALOG,
ZAP_SIGTYPE_SS7BOOST,
ZAP_SIGTYPE_M3UA
ZAP_SIGTYPE_M3UA,
ZAP_SIGTYPE_R2
} zap_signal_type_t;
typedef enum {
@ -279,6 +280,9 @@ typedef enum {
ZAP_COMMAND_GET_RX_GAIN,
ZAP_COMMAND_SET_TX_GAIN,
ZAP_COMMAND_GET_TX_GAIN,
ZAP_COMMAND_FLUSH_TX_BUFFERS,
ZAP_COMMAND_FLUSH_RX_BUFFERS,
ZAP_COMMAND_FLUSH_BUFFERS,
ZAP_COMMAND_COUNT
} zap_command_t;

File diff suppressed because it is too large Load Diff

View File

@ -202,7 +202,7 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
unsigned configured = 0, x;
if (type == ZAP_CHAN_TYPE_CAS) {
zap_log(ZAP_LOG_DEBUG, "Configuring CAS channels with abcd == 0x%X\n", cas_bits);
zap_log(ZAP_LOG_DEBUG, "Configuring Wanpipe CAS channels with abcd == 0x%X\n", cas_bits);
}
for(x = start; x < end; x++) {
zap_channel_t *chan;
@ -210,9 +210,14 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
const char *dtmf = "none";
sockfd = tdmv_api_open_span_chan(spanno, x);
if (sockfd == WP_INVALID_SOCKET) {
zap_log(ZAP_LOG_ERROR, "Failed to open wanpipe device span %d channel %d\n", spanno, x);
continue;
}
if (sockfd != WP_INVALID_SOCKET && zap_span_add_channel(span, sockfd, type, &chan) == ZAP_SUCCESS) {
if (zap_span_add_channel(span, sockfd, type, &chan) == ZAP_SUCCESS) {
wanpipe_tdm_api_t tdm_api;
memset(&tdm_api, 0, sizeof(tdm_api));
#ifdef LIBSANGOMA_VERSION
sangoma_status_t sangstatus;
sangoma_wait_obj_t *sangoma_wait_obj;
@ -225,8 +230,6 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
chan->mod_data = sangoma_wait_obj;
#endif
memset(&tdm_api,0,sizeof(tdm_api));
chan->physical_span_id = spanno;
chan->physical_chan_id = x;
chan->rate = 8000;
@ -237,7 +240,7 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
dtmf = "software";
/* FIXME: Handle Error Condition Check for return code */
err= sangoma_tdm_get_hw_coding(chan->sockfd, &tdm_api);
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;
@ -270,15 +273,26 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
if (type == ZAP_CHAN_TYPE_CAS ||
((span->trunk_type == ZAP_TRUNK_T1 || span->trunk_type == ZAP_TRUNK_E1) && type != ZAP_CHAN_TYPE_B)) {
#ifdef LIBSANGOMA_VERSION
sangoma_tdm_write_rbs(chan->sockfd,&tdm_api,chan->physical_chan_id,wanpipe_swap_bits(cas_bits));
sangoma_tdm_write_rbs(chan->sockfd,&tdm_api,chan->physical_chan_id, wanpipe_swap_bits(cas_bits));
/* this should probably be done for old libsangoma but I am not sure if the API is available and I'm lazy to check,
The poll rate is hard coded to 100 per second (done in the driver, is the max rate of polling allowed by wanpipe)
*/
if (sangoma_tdm_enable_rbs_events(chan->sockfd, &tdm_api, 100)) {
zap_log(ZAP_LOG_ERROR, "Failed to enable RBS/CAS events in device %d:%d fd:%d\n", chan->span_id, chan->chan_id, sockfd);
continue;
}
/* probably done by the driver but lets write defensive code this time */
sangoma_flush_bufs(chan->sockfd, &tdm_api);
#else
sangoma_tdm_write_rbs(chan->sockfd,&tdm_api,wanpipe_swap_bits(cas_bits));
sangoma_tdm_write_rbs(chan->sockfd,&tdm_api, wanpipe_swap_bits(cas_bits));
#endif
}
if (!zap_strlen_zero(name)) {
zap_copy_string(chan->chan_name, name, sizeof(chan->chan_name));
}
if (!zap_strlen_zero(number)) {
zap_copy_string(chan->chan_number, number, sizeof(chan->chan_number));
}
@ -288,7 +302,7 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
spanno, x, chan->span_id, chan->chan_id, sockfd, dtmf);
} else {
zap_log(ZAP_LOG_ERROR, "failure configuring device s%dc%d\n", spanno, x);
zap_log(ZAP_LOG_ERROR, "zap_span_add_channel failed for wanpipe span %d channel %d\n", spanno, x);
}
}
@ -371,15 +385,13 @@ static ZIO_CONFIGURE_SPAN_FUNCTION(wanpipe_configure_span)
}
if (!(sp && ch)) {
zap_log(ZAP_LOG_ERROR, "Invalid input\n");
zap_log(ZAP_LOG_ERROR, "No valid wanpipe span and channel was specified\n");
continue;
}
channo = atoi(ch);
spanno = atoi(sp);
if (channo < 0) {
zap_log(ZAP_LOG_ERROR, "Invalid channel number %d\n", channo);
continue;
@ -528,16 +540,24 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
case ZAP_COMMAND_SET_CAS_BITS:
{
#ifdef LIBSANGOMA_VERSION
err=sangoma_tdm_write_rbs(zchan->sockfd,&tdm_api,zchan->physical_chan_id,wanpipe_swap_bits(ZAP_COMMAND_OBJ_INT));
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));
err = sangoma_tdm_write_rbs(zchan->sockfd, &tdm_api, wanpipe_swap_bits(ZAP_COMMAND_OBJ_INT));
#endif
}
break;
case ZAP_COMMAND_GET_CAS_BITS:
{
/* wanpipe does not has a command to get the CAS bits so we emulate it */
ZAP_COMMAND_OBJ_INT = zchan->cas_bits;
#ifdef LIBSANGOMA_VERSION
unsigned char rbsbits;
err = sangoma_tdm_read_rbs(zchan->sockfd, &tdm_api, zchan->physical_chan_id, &rbsbits);
if (!err) {
ZAP_COMMAND_OBJ_INT = wanpipe_swap_bits(rbsbits);
}
#else
// does sangoma_tdm_read_rbs is available here?
ZAP_COMMAND_OBJ_INT = zchan->rx_cas_bits;
#endif
}
break;
default:
@ -817,7 +837,6 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
{
uint32_t i,err;
zap_oob_event_t event_id;
for(i = 1; i <= span->chan_count; i++) {
if (span->channels[i]->last_event_time && !zap_test_flag(span->channels[i], ZAP_CHANNEL_EVENT)) {
uint32_t diff = (uint32_t)(zap_current_time_in_ms() - span->channels[i]->last_event_time);
@ -856,7 +875,7 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
memset(&tdm_api, 0, sizeof(tdm_api));
zap_clear_flag(span->channels[i], ZAP_CHANNEL_EVENT);
err=sangoma_tdm_read_event(zchan->sockfd,&tdm_api);
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;
@ -926,9 +945,7 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
case WP_TDMAPI_EVENT_RBS:
{
event_id = ZAP_OOB_CAS_BITS_CHANGE;
/* save the CAS bits, user should retrieve it with ZAP_COMMAND_GET_CAS_BITS
is there a best play to store this? instead of adding cas_bits member to zap_chan? */
span->channels[i]->cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits);
span->channels[i]->rx_cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits);
}
break;
case WP_TDMAPI_EVENT_DTMF:

View File

@ -780,7 +780,6 @@ static ZIO_COMMAND_FUNCTION(zt_command)
if (zchan->effective_codec == ZAP_CODEC_SLIN) {
zchan->packet_len *= 2;
}
}
}
break;
@ -792,21 +791,42 @@ static ZIO_COMMAND_FUNCTION(zt_command)
break;
case ZAP_COMMAND_GET_CAS_BITS:
{
/* probably we should call ZT_GETRXBITS instead? */
ZAP_COMMAND_OBJ_INT = zchan->cas_bits;
err = ioctl(zchan->sockfd, codes.GETRXBITS, &zchan->rx_cas_bits);
if (!err) {
ZAP_COMMAND_OBJ_INT = zchan->rx_cas_bits;
}
}
break;
case ZAP_COMMAND_FLUSH_TX_BUFFERS:
{
int flushmode = ZT_FLUSH_WRITE;
err = ioctl(zchan->sockfd, codes.FLUSH, &flushmode);
}
break;
case ZAP_COMMAND_FLUSH_RX_BUFFERS:
{
int flushmode = ZT_FLUSH_READ;
err = ioctl(zchan->sockfd, codes.FLUSH, &flushmode);
}
break;
case ZAP_COMMAND_FLUSH_BUFFERS:
{
int flushmode = ZT_FLUSH_BOTH;
err = ioctl(zchan->sockfd, codes.FLUSH, &flushmode);
}
break;
default:
err = ZAP_NOTIMPL;
break;
};
if (err) {
if (err && err != ZAP_NOTIMPL) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "%s", strerror(errno));
return ZAP_FAIL;
}
return ZAP_SUCCESS;
return err == 0 ? ZAP_SUCCESS : err;
}
/**
@ -1019,7 +1039,7 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event)
if (err) {
return ZAP_FAIL;
}
span->channels[i]->cas_bits = bits;
span->channels[i]->rx_cas_bits = bits;
}
break;
default:

86
libs/freetdm/src/testr2.c Normal file
View File

@ -0,0 +1,86 @@
#include "openzap.h"
#include <signal.h>
static int R = 0;
static zap_mutex_t *mutex = NULL;
static ZIO_SIGNAL_CB_FUNCTION(on_r2_signal)
{
zap_log(ZAP_LOG_DEBUG, "Got R2 channel sig [%s] in channel\n", zap_signal_event2str(sigmsg->event_id), sigmsg->channel->physical_chan_id);
return ZAP_SUCCESS;
}
static void handle_SIGINT(int sig)
{
zap_mutex_lock(mutex);
R = 0;
zap_mutex_unlock(mutex);
return;
}
int main(int argc, char *argv[])
{
zap_span_t *span;
zap_mutex_create(&mutex);
zap_global_set_default_logger(ZAP_LOG_LEVEL_DEBUG);
if (argc < 2) {
printf("umm no\n");
exit(-1);
}
if (zap_global_init() != ZAP_SUCCESS) {
fprintf(stderr, "Error loading OpenZAP\n");
exit(-1);
}
printf("OpenZAP loaded\n");
if (zap_span_find(atoi(argv[1]), &span) != ZAP_SUCCESS) {
fprintf(stderr, "Error finding OpenZAP span\n");
goto done;
}
if (zap_configure_span("r2", span, on_r2_signal,
"variant", "mx",
"max_ani", 10,
"max_dnis", 4,
"logging", "all",
TAG_END) == ZAP_SUCCESS) {
zap_span_start(span);
} else {
fprintf(stderr, "Error starting R2 span\n");
goto done;
}
signal(SIGINT, handle_SIGINT);
zap_mutex_lock(mutex);
R = 1;
zap_mutex_unlock(mutex);
while(R) {
zap_sleep(1 * 1000);
}
done:
zap_global_destroy();
return 1;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
*/

View File

@ -216,14 +216,14 @@ OZ_DECLARE (int) zap_config_get_cas_bits(char *strvalue, unsigned char *outbits)
int x = 0;
char *double_colon = strchr(strvalue, ':');
if (!double_colon) {
zap_log(ZAP_LOG_ERROR, "No CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", double_colon);
zap_log(ZAP_LOG_ERROR, "No CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", strvalue);
return -1;
}
double_colon++;
*outbits = 0;
cas_bits[4] = 0;
if (sscanf(double_colon, "%c%c%c%c", &cas_bits[0], &cas_bits[1], &cas_bits[2], &cas_bits[3]) != 4) {
zap_log(ZAP_LOG_ERROR, "Invalid CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", double_colon);
zap_log(ZAP_LOG_ERROR, "Invalid CAS bits specified: '%s', :xxxx definition expected, where x is 1 or 0\n", double_colon);
return -1;
}
zap_log(ZAP_LOG_DEBUG, "CAS bits specification found: %s\n", cas_bits);

View File

@ -1522,14 +1522,17 @@ OZ_DECLARE(zap_status_t) zap_channel_command(zap_channel_t *zchan, zap_command_t
if (!zchan->zio->command) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "method not implemented");
zap_log(ZAP_LOG_ERROR, "no commnand functon!\n");
zap_log(ZAP_LOG_ERROR, "no command function defined by the I/O openzap module!\n");
GOTO_STATUS(done, ZAP_FAIL);
}
status = zchan->zio->command(zchan, command, obj);
done:
if (status == ZAP_NOTIMPL) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "I/O command %d not implemented in backend", command);
zap_log(ZAP_LOG_ERROR, "I/O backend does not support command %d!\n", command);
}
done:
zap_mutex_unlock(zchan->mutex);
return status;