ranlib $(MYLIB)
testapp: testapp.c $(MYLIB)
- $(CC) -L. -Iinclude testapp.c -o testapp -lopenzap -lm
+ $(CC) -L. -Iinclude testapp.c -o testapp -lopenzap -lm -lpthread
priserver.o: priserver.c
$(CC) $(TMP) -c sangoma_pri.c -o sangoma_pri.o
priserver: $(MYLIB) priserver.o sangoma_pri.o
- $(CC) sangoma_pri.o priserver.o -L. -o priserver -lopenzap -lm ../../libpri-1.2.4/libpri.a
+ $(CC) sangoma_pri.o priserver.o -L. -o priserver -lopenzap -lm -lpthread ../../libpri-1.2.4/libpri.a
openzap.o: openzap.c
$(CC) $(MOD_CFLAGS) $(CC_CFLAGS) $(CFLAGS) -c $< -o $@
--- /dev/null
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * g711.c - A-law and u-law transcoding routines
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2006 Steve Underwood
+ *
+ * Despite my general liking of the GPL, I place this code in the
+ * public domain for the benefit of all mankind - even the slimy
+ * ones who might try to proprietize my work and use it to my
+ * detriment.
+ *
+ * $Id: g711.c,v 1.1 2006/06/07 15:46:39 steveu Exp $
+ */
+
+/*! \file */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#ifndef _MSC_VER
+#include <inttypes.h>
+#ifdef HAVE_TGMATH_H
+#include <tgmath.h>
+#endif
+#endif
+
+#include "g711.h"
+
+/* Copied from the CCITT G.711 specification */
+static const uint8_t ulaw_to_alaw_table[256] =
+{
+ 42, 43, 40, 41, 46, 47, 44, 45, 34, 35, 32, 33, 38, 39, 36, 37,
+ 58, 59, 56, 57, 62, 63, 60, 61, 50, 51, 48, 49, 54, 55, 52, 53,
+ 10, 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, 1, 6, 7, 4, 26,
+ 27, 24, 25, 30, 31, 28, 29, 18, 19, 16, 17, 22, 23, 20, 21, 106,
+ 104, 105, 110, 111, 108, 109, 98, 99, 96, 97, 102, 103, 100, 101, 122, 120,
+ 126, 127, 124, 125, 114, 115, 112, 113, 118, 119, 116, 117, 75, 73, 79, 77,
+ 66, 67, 64, 65, 70, 71, 68, 69, 90, 91, 88, 89, 94, 95, 92, 93,
+ 82, 82, 83, 83, 80, 80, 81, 81, 86, 86, 87, 87, 84, 84, 85, 85,
+ 170, 171, 168, 169, 174, 175, 172, 173, 162, 163, 160, 161, 166, 167, 164, 165,
+ 186, 187, 184, 185, 190, 191, 188, 189, 178, 179, 176, 177, 182, 183, 180, 181,
+ 138, 139, 136, 137, 142, 143, 140, 141, 130, 131, 128, 129, 134, 135, 132, 154,
+ 155, 152, 153, 158, 159, 156, 157, 146, 147, 144, 145, 150, 151, 148, 149, 234,
+ 232, 233, 238, 239, 236, 237, 226, 227, 224, 225, 230, 231, 228, 229, 250, 248,
+ 254, 255, 252, 253, 242, 243, 240, 241, 246, 247, 244, 245, 203, 201, 207, 205,
+ 194, 195, 192, 193, 198, 199, 196, 197, 218, 219, 216, 217, 222, 223, 220, 221,
+ 210, 210, 211, 211, 208, 208, 209, 209, 214, 214, 215, 215, 212, 212, 213, 213
+};
+
+/* These transcoding tables are copied from the CCITT G.711 specification. To achieve
+ optimal results, do not change them. */
+
+static const uint8_t alaw_to_ulaw_table[256] =
+{
+ 42, 43, 40, 41, 46, 47, 44, 45, 34, 35, 32, 33, 38, 39, 36, 37,
+ 57, 58, 55, 56, 61, 62, 59, 60, 49, 50, 47, 48, 53, 54, 51, 52,
+ 10, 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, 1, 6, 7, 4, 5,
+ 26, 27, 24, 25, 30, 31, 28, 29, 18, 19, 16, 17, 22, 23, 20, 21,
+ 98, 99, 96, 97, 102, 103, 100, 101, 93, 93, 92, 92, 95, 95, 94, 94,
+ 116, 118, 112, 114, 124, 126, 120, 122, 106, 107, 104, 105, 110, 111, 108, 109,
+ 72, 73, 70, 71, 76, 77, 74, 75, 64, 65, 63, 63, 68, 69, 66, 67,
+ 86, 87, 84, 85, 90, 91, 88, 89, 79, 79, 78, 78, 82, 83, 80, 81,
+ 170, 171, 168, 169, 174, 175, 172, 173, 162, 163, 160, 161, 166, 167, 164, 165,
+ 185, 186, 183, 184, 189, 190, 187, 188, 177, 178, 175, 176, 181, 182, 179, 180,
+ 138, 139, 136, 137, 142, 143, 140, 141, 130, 131, 128, 129, 134, 135, 132, 133,
+ 154, 155, 152, 153, 158, 159, 156, 157, 146, 147, 144, 145, 150, 151, 148, 149,
+ 226, 227, 224, 225, 230, 231, 228, 229, 221, 221, 220, 220, 223, 223, 222, 222,
+ 244, 246, 240, 242, 252, 254, 248, 250, 234, 235, 232, 233, 238, 239, 236, 237,
+ 200, 201, 198, 199, 204, 205, 202, 203, 192, 193, 191, 191, 196, 197, 194, 195,
+ 214, 215, 212, 213, 218, 219, 216, 217, 207, 207, 206, 206, 210, 211, 208, 209
+};
+
+uint8_t alaw_to_ulaw(uint8_t alaw)
+{
+ return alaw_to_ulaw_table[alaw];
+}
+/*- End of function --------------------------------------------------------*/
+
+uint8_t ulaw_to_alaw(uint8_t ulaw)
+{
+ return ulaw_to_alaw_table[ulaw];
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/
#include "g711.h"
#include "libteletone.h"
#include "zap_buffer.h"
+#include "zap_threadmutex.h"
#ifdef NDEBUG
#undef assert
#define ZAP_MAX_CHANNELS_SPAN 513
#define ZAP_MAX_SPANS_INTERFACE 33
-
+#define GOTO_STATUS(label,st) status = st; goto label ;
#define zap_true(expr)\
(expr && ( !strcasecmp(expr, "yes") ||\
zap_span_flag_t flags;
struct zap_software_interface *zint;
zint_event_cb_t event_callback;
+ zap_mutex_t *mutex;
zap_channel_t channels[ZAP_MAX_CHANNELS_SPAN];
};
zap_status_t zap_span_find(const char *name, uint32_t id, zap_span_t **span);
zap_status_t zap_span_create(zap_software_interface_t *zint, zap_span_t **span);
+zap_status_t zap_span_close_all(zap_software_interface_t *zint);
zap_status_t zap_span_add_channel(zap_span_t *span, zap_socket_t sockfd, zap_chan_type_t type, zap_channel_t **chan);
zap_status_t zap_span_set_event_callback(zap_span_t *span, zint_event_cb_t event_callback);
zap_status_t zap_channel_set_event_callback(zap_channel_t *zchan, zint_event_cb_t event_callback);
zap_status_t zap_channel_open_any(const char *name, uint32_t span_id, zap_direction_t direction, zap_channel_t **zchan);
zap_status_t zap_channel_close(zap_channel_t **zchan);
zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, void *obj);
-zap_status_t zap_channel_wait(zap_channel_t *zchan, zap_wait_flag_t *flags, uint32_t to);
+zap_status_t zap_channel_wait(zap_channel_t *zchan, zap_wait_flag_t *flags, int32_t to);
zap_status_t zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *datalen);
zap_status_t zap_channel_write(zap_channel_t *zchan, void *data, zap_size_t *datalen);
zap_status_t zap_global_init(void);
memcpy( wan_udp.wan_udphdr_data, (void*)tdm_api_cmd, sizeof(wanpipe_tdm_api_cmd_t));
- if(DeviceIoControl(
+ if (DeviceIoControl(
fd,
IoctlManagementCommand,
(LPVOID)&wan_udp,
return 1;
}
- if(wan_udp.wan_udphdr_return_code != WAN_CMD_OK){
+ if (wan_udp.wan_udphdr_return_code != WAN_CMD_OK){
return 2;
}
void __inline__ tdmv_api_close_socket(sng_fd_t *sp)
{
- if( *sp != WP_INVALID_SOCKET){
+ if ( *sp != WP_INVALID_SOCKET){
#if defined(__WINDOWS__)
CloseHandle(*sp);
#else
(LPOVERLAPPED)NULL
);
- if((wan_udp.wan_udphdr_return_code) || (*(int*)&wan_udp.wan_udphdr_data[0] != 1)){
+ 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);
}
/* 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)
+static __inline__ int tdmv_api_wait_socket(sng_fd_t fd, int timeout, int *flags)
{
#if defined(__WINDOWS__)
DWORD ln;
memset(&api_poll, 0x00, sizeof(API_POLL_STRUCT));
- api_poll.user_flags_bitmap = flags;
+ api_poll.user_flags_bitmap = *flags;
api_poll.timeout = timeout;
if (!DeviceIoControl(
return -1;
}
+ *flags = 0;
+
switch(api_poll.operation_status)
{
case SANG_STATUS_RX_DATA_AVAILABLE:
return -1;
}
- if(api_poll.poll_events_bitmap == 0){
+ if (api_poll.poll_events_bitmap == 0){
return -1;
}
- if(api_poll.poll_events_bitmap & POLL_EVENT_TIMEOUT){
+ if (api_poll.poll_events_bitmap & POLL_EVENT_TIMEOUT) {
return 0;
}
- return api_poll.poll_events_bitmap;
+ *flags = api_poll.poll_events_bitmap;
+
+ return 1;
#else
struct pollfd pfds[1];
int res;
memset(&pfds[0], 0, sizeof(pfds[0]));
pfds[0].fd = fd;
- pfds[0].events = flags;
+ pfds[0].events = *flags;
res = poll(pfds, 1, timeout);
+ *flags = 0;
- if (res == 0) {
- return 0;
- }
-
- if (res < 0) {
- return -1;
+ if (pfds[0].revents & POLLERR) {
+ res = -1;
}
- if ((pfds[0].revents & POLLERR)) {
- return -1;
+ if (res > 0) {
+ *flags = pfds[0].revents;
}
- return pfds[0].revents;
+ return res;
#endif
}
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)){
+ if (hdrlen != sizeof(wp_tdm_api_rx_hdr_t)){
return -1;
}
- if(!DeviceIoControl(
+ if (!DeviceIoControl(
fd,
IoctlReadCommand,
(LPVOID)NULL,
switch(pri->operation_status)
{
case SANG_STATUS_RX_DATA_AVAILABLE:
- if(pri->data_length > datalen){
+ if (pri->data_length > datalen){
break;
}
memcpy(databuf, rx_data.data, pri->data_length);
pri->data_length = datalen;
memcpy(local_tx_data.data, databuf, pri->data_length);
- if(!DeviceIoControl(
+ if (!DeviceIoControl(
fd,
IoctlWriteCommand,
(LPVOID)&local_tx_data,
memset(&msg,0,sizeof(struct msghdr));
- iov[0].iov_len=hdrlen;
- iov[0].iov_base=hdrbuf;
+ iov[0].iov_len = hdrlen;
+ iov[0].iov_base = hdrbuf;
- iov[1].iov_len=datalen;
- iov[1].iov_base=databuf;
+ iov[1].iov_len = datalen;
+ iov[1].iov_base = databuf;
- msg.msg_iovlen=2;
- msg.msg_iov=iov;
+ msg.msg_iovlen = 2;
+ msg.msg_iov = iov;
- bsent = write(fd,&msg,datalen+hdrlen);
+ bsent = write(fd, &msg, datalen + hdrlen);
if (bsent > 0){
- bsent-=sizeof(wp_tdm_api_tx_hdr_t);
+ bsent -= sizeof(wp_tdm_api_tx_hdr_t);
}
#endif
return bsent;
zap_status_t zap_thread_create_detached_ex(zap_thread_function_t func, void *data, zap_size_t stack_size);
void zap_thread_override_default_stacksize(zap_size_t size);
zap_status_t zap_mutex_create(zap_mutex_t **mutex);
-zap_status_t zap_mutex_destroy(zap_mutex_t *mutex);
+zap_status_t zap_mutex_destroy(zap_mutex_t **mutex);
zap_status_t zap_mutex_lock(zap_mutex_t *mutex);
zap_status_t zap_mutex_trylock(zap_mutex_t *mutex);
zap_status_t zap_mutex_unlock(zap_mutex_t *mutex);
typedef enum {
ZAP_NO_FLAGS = 0,
- ZAP_READ = (1 << 0),
- ZAP_WRITE = (1 << 1),
- ZAP_ERROR = (1 << 2)
+ ZAP_READ = (1 << 0),
+ ZAP_WRITE = (1 << 1),
+ ZAP_EVENTS = (1 << 2)
} zap_wait_flag_t;
typedef enum {
#define ZINT_OPEN_ARGS (zap_channel_t *zchan)
#define ZINT_CLOSE_ARGS (zap_channel_t *zchan)
#define ZINT_COMMAND_ARGS (zap_channel_t *zchan, zap_command_t command, void *obj)
-#define ZINT_WAIT_ARGS (zap_channel_t *zchan, zap_wait_flag_t *flags, uint32_t to)
+#define ZINT_WAIT_ARGS (zap_channel_t *zchan, zap_wait_flag_t *flags, int32_t to)
#define ZINT_READ_ARGS (zap_channel_t *zchan, void *data, zap_size_t *datalen)
#define ZINT_WRITE_ARGS (zap_channel_t *zchan, void *data, zap_size_t *datalen)
static struct {
zap_hash_t *interface_hash;
+ zap_mutex_t *mutex;
} globals;
static char *LEVEL_NAMES[] = {
zap_set_flag(new_span, ZAP_SPAN_CONFIGURED);
new_span->span_id = zint->span_index;
new_span->zint = zint;
+ zap_mutex_create(&new_span->mutex);
*span = new_span;
return ZAP_SUCCESS;
}
return ZAP_FAIL;
}
+zap_status_t zap_span_close_all(zap_software_interface_t *zint)
+{
+ zap_span_t *span;
+ uint32_t i;
+
+ for(i = 0; i < zint->span_index; i++) {
+ span = &zint->spans[i];
+ if (span->mutex) {
+ zap_mutex_destroy(&span->mutex);
+ }
+ }
+
+ return i ? ZAP_SUCCESS : ZAP_FAIL;
+}
+
zap_status_t zap_span_add_channel(zap_span_t *span, zap_socket_t sockfd, zap_chan_type_t type, zap_channel_t **chan)
{
if (span->chan_count < ZAP_MAX_CHANNELS_SPAN) {
zap_status_t zap_span_find(const char *name, uint32_t id, zap_span_t **span)
{
- zap_software_interface_t *zint = (zap_software_interface_t *) hashtable_search(globals.interface_hash, (char *)name);
+ zap_software_interface_t *zint;
zap_span_t *fspan;
+ zap_mutex_lock(globals.mutex);
+ zint = (zap_software_interface_t *) hashtable_search(globals.interface_hash, (char *)name);
+ zap_mutex_unlock(globals.mutex);
+
if (!zint) {
return ZAP_FAIL;
}
zap_status_t zap_span_set_event_callback(zap_span_t *span, zint_event_cb_t event_callback)
{
+ zap_mutex_lock(span->mutex);
span->event_callback = event_callback;
+ zap_mutex_unlock(span->mutex);
return ZAP_SUCCESS;
}
zap_status_t zap_channel_set_event_callback(zap_channel_t *zchan, zint_event_cb_t event_callback)
{
+ zap_mutex_lock(zchan->span->mutex);
zchan->event_callback = event_callback;
+ zap_mutex_unlock(zchan->span->mutex);
return ZAP_SUCCESS;
}
zap_status_t zap_channel_open_any(const char *name, uint32_t span_id, zap_direction_t direction, zap_channel_t **zchan)
{
- zap_software_interface_t *zint = (zap_software_interface_t *) hashtable_search(globals.interface_hash, (char *)name);
+ zap_software_interface_t *zint;
zap_status_t status = ZAP_FAIL;
zap_channel_t *check;
uint32_t i,j;
zap_span_t *span;
uint32_t span_max;
+ zap_mutex_lock(globals.mutex);
+ zint = (zap_software_interface_t *) hashtable_search(globals.interface_hash, (char *)name);
+ zap_mutex_unlock(globals.mutex);
+
if (!zint) {
zap_log(ZAP_LOG_ERROR, "Invalid interface name!\n");
return ZAP_FAIL;
j = span_max;
}
-
+ zap_mutex_lock(globals.mutex);
for(;;) {
span = &zint->spans[j];
}
}
+ zap_mutex_unlock(globals.mutex);
+
return status;
}
+static zap_status_t zap_channel_reset(zap_channel_t *zchan)
+{
+ zap_clear_flag(zchan, ZAP_CHANNEL_OPEN);
+ zchan->event_callback = NULL;
+ zap_clear_flag(zchan, ZAP_CHANNEL_DTMF_DETECT);
+ zap_clear_flag(zchan, ZAP_CHANNEL_SUPRESS_DTMF);
+ if (zchan->tone_session.buffer) {
+ teletone_destroy_session(&zchan->tone_session);
+ memset(&zchan->tone_session, 0, sizeof(zchan->tone_session));
+ }
+ if (zchan->dtmf_buffer) {
+ zap_buffer_destroy(&zchan->dtmf_buffer);
+ }
+ zchan->dtmf_on = zchan->dtmf_off = 0;
+
+ if (zap_test_flag(zchan, ZAP_CHANNEL_TRANSCODE)) {
+ zchan->effective_codec = zchan->native_codec;
+ zchan->packet_len = zchan->native_interval * (zchan->effective_codec == ZAP_CODEC_SLIN ? 16 : 8);
+ zap_clear_flag(zchan, ZAP_CHANNEL_TRANSCODE);
+ }
+
+ return ZAP_SUCCESS;
+}
+
+
+
zap_status_t zap_channel_open(const char *name, uint32_t span_id, uint32_t chan_id, zap_channel_t **zchan)
{
- zap_software_interface_t *zint = (zap_software_interface_t *) hashtable_search(globals.interface_hash, (char *)name);
+ zap_software_interface_t *zint;
zap_status_t status = ZAP_FAIL;
+ zap_mutex_lock(globals.mutex);
+ zint = (zap_software_interface_t *) hashtable_search(globals.interface_hash, (char *)name);
+ zap_mutex_unlock(globals.mutex);
+
+
if (span_id < ZAP_MAX_SPANS_INTERFACE && chan_id < ZAP_MAX_CHANNELS_SPAN && zint) {
zap_channel_t *check;
+ zap_mutex_lock(zint->spans[span_id].mutex);
check = &zint->spans[span_id].channels[chan_id];
+
if (zap_test_flag(check, ZAP_CHANNEL_READY) && ! zap_test_flag(check, ZAP_CHANNEL_OPEN)) {
status = check->zint->open(check);
if (status == ZAP_SUCCESS) {
zap_set_flag(check, ZAP_CHANNEL_OPEN);
*zchan = check;
}
- return status;
}
+ zap_mutex_unlock(zint->spans[span_id].mutex);
}
return status;
check = *zchan;
assert(check != NULL);
*zchan = NULL;
-
+
+ zap_mutex_lock(check->span->mutex);
if (zap_test_flag(check, ZAP_CHANNEL_OPEN)) {
status = check->zint->close(check);
if (status == ZAP_SUCCESS) {
- zap_clear_flag(check, ZAP_CHANNEL_OPEN);
- check->event_callback = NULL;
- zap_clear_flag(check, ZAP_CHANNEL_DTMF_DETECT);
- zap_clear_flag(check, ZAP_CHANNEL_SUPRESS_DTMF);
- if (check->tone_session.buffer) {
- teletone_destroy_session(&check->tone_session);
- memset(&check->tone_session, 0, sizeof(check->tone_session));
- }
- if (check->dtmf_buffer) {
- zap_buffer_destroy(&check->dtmf_buffer);
- }
- check->dtmf_on = check->dtmf_off = 0;
+ zap_channel_reset(check);
*zchan = NULL;
}
}
+
+ zap_mutex_unlock(check->span->mutex);
return status;
}
zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, void *obj)
{
+ zap_status_t status = ZAP_FAIL;
+
assert(zchan != NULL);
assert(zchan->zint != NULL);
return ZAP_FAIL;
}
+ zap_mutex_lock(zchan->span->mutex);
+
switch(command) {
case ZAP_COMMAND_SET_INTERVAL:
{
zap_set_flag(zchan, ZAP_CHANNEL_BUFFER);
}
zchan->packet_len = zchan->native_interval * (zchan->effective_codec == ZAP_CODEC_SLIN ? 16 : 8);
- return ZAP_SUCCESS;
+ GOTO_STATUS(done, ZAP_SUCCESS);
}
}
break;
{
if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_INTERVAL)) {
ZAP_COMMAND_OBJ_INT = zchan->effective_interval;
- return ZAP_SUCCESS;
+ GOTO_STATUS(done, ZAP_SUCCESS);
}
}
break;
zap_set_flag(zchan, ZAP_CHANNEL_TRANSCODE);
}
zchan->packet_len = zchan->native_interval * (zchan->effective_codec == ZAP_CODEC_SLIN ? 16 : 8);
- return ZAP_SUCCESS;
+ GOTO_STATUS(done, ZAP_SUCCESS);
}
}
break;
{
if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_CODECS)) {
ZAP_COMMAND_OBJ_INT = zchan->effective_codec;
- return ZAP_SUCCESS;
+ GOTO_STATUS(done, ZAP_SUCCESS);
}
}
break;
teletone_dtmf_detect_init (&zchan->dtmf_detect, 8000);
zap_set_flag(zchan, ZAP_CHANNEL_DTMF_DETECT);
zap_set_flag(zchan, ZAP_CHANNEL_SUPRESS_DTMF);
- return ZAP_SUCCESS;
+ GOTO_STATUS(done, ZAP_SUCCESS);
} else {
snprintf(zchan->last_error, sizeof(zchan->last_error), "invalid command");
- return ZAP_FAIL;
+ GOTO_STATUS(done, ZAP_FAIL);
}
}
}
teletone_dtmf_detect_init (&zchan->dtmf_detect, 8000);
zap_clear_flag(zchan, ZAP_CHANNEL_DTMF_DETECT);
zap_clear_flag(zchan, ZAP_CHANNEL_SUPRESS_DTMF);
- return ZAP_SUCCESS;
+ GOTO_STATUS(done, ZAP_SUCCESS);
} else {
snprintf(zchan->last_error, sizeof(zchan->last_error), "invalid command");
- return ZAP_FAIL;
+ GOTO_STATUS(done, ZAP_FAIL);
}
}
}
{
if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_DTMF)) {
ZAP_COMMAND_OBJ_INT = zchan->dtmf_on;
- return ZAP_SUCCESS;
+ GOTO_STATUS(done, ZAP_SUCCESS);
}
}
break;
{
if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_DTMF)) {
ZAP_COMMAND_OBJ_INT = zchan->dtmf_on;
- return ZAP_SUCCESS;
+ GOTO_STATUS(done, ZAP_SUCCESS);
}
}
break;
int val = ZAP_COMMAND_OBJ_INT;
if (val > 10 && val < 1000) {
zchan->dtmf_on = val;
- return ZAP_SUCCESS;
+ GOTO_STATUS(done, ZAP_SUCCESS);
} else {
snprintf(zchan->last_error, sizeof(zchan->last_error), "invalid value %d range 10-1000", val);
- return ZAP_FAIL;
+ GOTO_STATUS(done, ZAP_FAIL);
}
}
}
int val = ZAP_COMMAND_OBJ_INT;
if (val > 10 && val < 1000) {
zchan->dtmf_off = val;
- return ZAP_SUCCESS;
+ GOTO_STATUS(done, ZAP_SUCCESS);
} else {
snprintf(zchan->last_error, sizeof(zchan->last_error), "invalid value %d range 10-1000", val);
- return ZAP_FAIL;
+ GOTO_STATUS(done, ZAP_FAIL);
}
}
}
case ZAP_COMMAND_SEND_DTMF:
{
if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_DTMF)) {
- zap_status_t status;
char *cur;
char *digits = ZAP_COMMAND_OBJ_CHAR_P;
if (!zchan->dtmf_buffer) {
if ((status = zchan_activate_dtmf_buffer(zchan)) != ZAP_SUCCESS) {
- return status;
+ GOTO_STATUS(done, status);
}
}
zap_log(ZAP_LOG_DEBUG, "Adding DTMF SEQ [%s]\n", digits);
-
+
for (cur = digits; *cur; cur++) {
int wrote = 0;
if ((wrote = teletone_mux_tones(&zchan->tone_session, &zchan->tone_session.TONES[(int)*cur]))) {
}
zchan->skip_read_frames = 200;
- return ZAP_SUCCESS;
+ GOTO_STATUS(done, ZAP_SUCCESS);
}
}
break;
if (!zchan->zint->command) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "method not implemented");
- return ZAP_FAIL;
+ GOTO_STATUS(done, ZAP_FAIL);
}
- return zchan->zint->command(zchan, command, obj);
+ status = zchan->zint->command(zchan, command, obj);
+
+ done:
+ zap_mutex_unlock(zchan->span->mutex);
+ return status;
}
-zap_status_t zap_channel_wait(zap_channel_t *zchan, zap_wait_flag_t *flags, uint32_t to)
+zap_status_t zap_channel_wait(zap_channel_t *zchan, zap_wait_flag_t *flags, int32_t to)
{
assert(zchan != NULL);
assert(zchan->zint != NULL);
return status;
}
+static struct {
+ zap_software_interface_t *wanpipe_interface;
+ zap_software_interface_t *zt_interface;
+} interfaces;
+
zap_status_t zap_global_init(void)
{
zap_config_t cfg;
char *var, *val;
uint32_t configured = 0;
- zap_software_interface_t *zint;
int modcount;
+ memset(&interfaces, 0, sizeof(interfaces));
globals.interface_hash = create_hashtable(16, hashfromstring, equalkeys);
- zint = NULL;
modcount = 0;
-
+ zap_mutex_create(&globals.mutex);
+
#ifdef ZAP_WANPIPE_SUPPORT
- if (wanpipe_init(&zint) == ZAP_SUCCESS) {
- hashtable_insert(globals.interface_hash, (void *)zint->name, zint);
+ if (wanpipe_init(&interfaces.wanpipe_interface) == ZAP_SUCCESS) {
+ zap_mutex_lock(globals.mutex);
+ hashtable_insert(globals.interface_hash, (void *)interfaces.wanpipe_interface->name, interfaces.wanpipe_interface);
+ zap_mutex_unlock(globals.mutex);
modcount++;
} else {
zap_log(ZAP_LOG_ERROR, "Error initilizing wanpipe.\n");
}
#endif
- zint = NULL;
+
#ifdef ZAP_ZT_SUPPORT
- if (zt_init(&zint) == ZAP_SUCCESS) {
- hashtable_insert(globals.interface_hash, (void *)zint->name, zint);
+ if (zt_init(&interfaces.zt_interface) == ZAP_SUCCESS) {
+ zap_mutex_lock(globals.mutex);
+ hashtable_insert(globals.interface_hash, (void *)interfaces.zt_interface->name, interfaces.zt_interface);
+ zap_mutex_unlock(globals.mutex);
modcount++;
} else {
zap_log(ZAP_LOG_ERROR, "Error initilizing zt.\n");
if (!strcasecmp(cfg.category, "openzap")) {
if (!strcmp(var, "load")) {
zap_software_interface_t *zint;
-
+
+ zap_mutex_lock(globals.mutex);
zint = (zap_software_interface_t *) hashtable_search(globals.interface_hash, val);
+ zap_mutex_unlock(globals.mutex);
+
if (zint) {
if (zint->configure(zint) == ZAP_SUCCESS) {
configured++;
zap_status_t zap_global_destroy(void)
{
-
#ifdef ZAP_ZT_SUPPORT
- zt_destroy();
+ if (interfaces.zt_interface) {
+ zt_destroy();
+ zap_span_close_all(interfaces.zt_interface);
+ }
#endif
#ifdef ZAP_WANPIPE_SUPPORT
- wanpipe_destroy();
+ if (interfaces.wanpipe_interface) {
+ wanpipe_destroy();
+ zap_span_close_all(interfaces.wanpipe_interface);
+ }
#endif
hashtable_destroy(globals.interface_hash, 0);
-
+ zap_mutex_destroy(&globals.mutex);
return ZAP_SUCCESS;
}
printf("OpenZAP loaded\n");
top:
- if (zap_channel_open_any("wanpipe", 0, ZAP_TOP_DOWN, &chan) == ZAP_SUCCESS) {
+ //if (zap_channel_open_any("wanpipe", 0, ZAP_TOP_DOWN, &chan) == ZAP_SUCCESS) {
+ if (zap_channel_open("wanpipe", 1, 1, &chan) == ZAP_SUCCESS) {
int x = 0;
printf("opened channel %d:%d\n", chan->span_id, chan->chan_id);
zap_size_t len = sizeof(buf);
zap_wait_flag_t flags = ZAP_READ;
- if (zap_channel_wait(chan, &flags, 0) == ZAP_FAIL) {
+ if (zap_channel_wait(chan, &flags, -1) == ZAP_FAIL) {
printf("wait FAIL! %d [%s]\n", len, chan->last_error);
}
if (flags & ZAP_READ) {
return status;
}
-zap_status_t zap_mutex_destroy(zap_mutex_t *mutex)
+zap_status_t zap_mutex_destroy(zap_mutex_t **mutex)
{
+ zap_mutex_t *mp = *mutex;
+ *mutex = NULL;
#ifdef WIN32
- DeleteCriticalSection(&mutex->mutex);
+ DeleteCriticalSection(&mp->mutex);
#else
- if (pthread_mutex_destroy(&mutex->mutex))
+ if (pthread_mutex_destroy(&mp->mutex))
return ZAP_FAIL;
#endif
- free(mutex);
+ free(mp);
return ZAP_SUCCESS;
}
static ZINT_WAIT_FUNCTION(wanpipe_wait)
{
- zap_wait_flag_t inflags = *flags;
+ int32_t inflags = 0;
int result;
-
- result = tdmv_api_wait_socket(zchan->sockfd, to, inflags);
+
+ if (*flags & ZAP_READ) {
+ inflags |= POLLIN;
+ }
+
+ if (*flags & ZAP_WRITE) {
+ inflags |= POLLOUT;
+ }
+
+ if (*flags & ZAP_EVENTS) {
+ inflags |= POLLPRI;
+ }
+
+ result = tdmv_api_wait_socket(zchan->sockfd, to, &inflags);
*flags = ZAP_NO_FLAGS;
- if(result < 0){
+ if (result < 0){
snprintf(zchan->last_error, sizeof(zchan->last_error), "Poll failed");
return ZAP_FAIL;
}
return ZAP_TIMEOUT;
}
- if (result & POLLIN) {
+ if (inflags & POLLIN) {
*flags |= ZAP_READ;
}
- if (result & POLLOUT) {
+ if (inflags & POLLOUT) {
*flags |= ZAP_WRITE;
}
- if (result & POLLPRI) {
- *flags |= ZAP_ERROR;
+ if (inflags & POLLPRI) {
+ *flags |= ZAP_EVENTS;
}
return ZAP_SUCCESS;