From 5013baf37a0464c158a3bc948f322e81a9ce99bc Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 21 May 2007 17:48:13 +0000 Subject: [PATCH] update git-svn-id: http://svn.openzap.org/svn/openzap/trunk@62 a93c3328-9c30-0410-af19-c9cd2b2d52af --- libs/freetdm/src/Makefile | 4 +- libs/freetdm/src/g711.c | 92 +++++++++++ libs/freetdm/src/include/openzap.h | 7 +- libs/freetdm/src/include/sangoma_tdm_api.h | 63 +++---- libs/freetdm/src/include/zap_threadmutex.h | 2 +- libs/freetdm/src/include/zap_types.h | 8 +- libs/freetdm/src/openzap.c | 184 +++++++++++++++------ libs/freetdm/src/testapp.c | 5 +- libs/freetdm/src/zap_threadmutex.c | 10 +- libs/freetdm/src/zap_wanpipe.c | 28 +++- 10 files changed, 297 insertions(+), 106 deletions(-) create mode 100644 libs/freetdm/src/g711.c diff --git a/libs/freetdm/src/Makefile b/libs/freetdm/src/Makefile index 8ec0c6dd2d..50e4b6ba7b 100644 --- a/libs/freetdm/src/Makefile +++ b/libs/freetdm/src/Makefile @@ -44,7 +44,7 @@ $(MYLIB): $(OBJS) 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 @@ -54,7 +54,7 @@ sangoma_pri.o: sangoma_pri.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 $@ diff --git a/libs/freetdm/src/g711.c b/libs/freetdm/src/g711.c new file mode 100644 index 0000000000..8a5c58b835 --- /dev/null +++ b/libs/freetdm/src/g711.c @@ -0,0 +1,92 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * g711.c - A-law and u-law transcoding routines + * + * Written by Steve Underwood + * + * 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 +#endif + +#include +#include +#include +#include +#ifndef _MSC_VER +#include +#ifdef HAVE_TGMATH_H +#include +#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 ------------------------------------------------------------*/ diff --git a/libs/freetdm/src/include/openzap.h b/libs/freetdm/src/include/openzap.h index 8f4b012a80..256b4e8f9b 100644 --- a/libs/freetdm/src/include/openzap.h +++ b/libs/freetdm/src/include/openzap.h @@ -87,6 +87,7 @@ #include "g711.h" #include "libteletone.h" #include "zap_buffer.h" +#include "zap_threadmutex.h" #ifdef NDEBUG #undef assert @@ -96,7 +97,7 @@ #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") ||\ @@ -190,6 +191,7 @@ struct zap_span { 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]; }; @@ -211,6 +213,7 @@ struct zap_software_interface { 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); @@ -218,7 +221,7 @@ zap_status_t zap_channel_open(const char *name, uint32_t span_id, uint32_t chan_ 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); diff --git a/libs/freetdm/src/include/sangoma_tdm_api.h b/libs/freetdm/src/include/sangoma_tdm_api.h index a58caf5d8d..b8b40d61fb 100644 --- a/libs/freetdm/src/include/sangoma_tdm_api.h +++ b/libs/freetdm/src/include/sangoma_tdm_api.h @@ -107,7 +107,7 @@ static __inline__ int tdmv_api_ioctl(sng_fd_t fd, wanpipe_tdm_api_t *tdm_api_cmd 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, @@ -120,7 +120,7 @@ static __inline__ int tdmv_api_ioctl(sng_fd_t fd, wanpipe_tdm_api_t *tdm_api_cmd return 1; } - if(wan_udp.wan_udphdr_return_code != WAN_CMD_OK){ + if (wan_udp.wan_udphdr_return_code != WAN_CMD_OK){ return 2; } @@ -137,7 +137,7 @@ static __inline__ int tdmv_api_ioctl(sng_fd_t fd, wanpipe_tdm_api_t *tdm_api_cmd 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 @@ -186,7 +186,7 @@ static __inline__ sng_fd_t tdmv_api_open_span_chan(int span, int chan) (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); } @@ -218,7 +218,7 @@ static __inline__ sng_fd_t tdmv_api_open_span_chan(int span, int chan) /* 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; @@ -226,7 +226,7 @@ static __inline__ int tdmv_api_wait_socket(sng_fd_t fd, int timeout, int flags) 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( @@ -241,6 +241,8 @@ static __inline__ int tdmv_api_wait_socket(sng_fd_t fd, int timeout, int flags) return -1; } + *flags = 0; + switch(api_poll.operation_status) { case SANG_STATUS_RX_DATA_AVAILABLE: @@ -253,37 +255,36 @@ static __inline__ int tdmv_api_wait_socket(sng_fd_t fd, int timeout, int flags) 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 (pfds[0].revents & POLLERR) { + res = -1; } - if (res < 0) { - return -1; + if (res > 0) { + *flags = pfds[0].revents; } - if ((pfds[0].revents & POLLERR)) { - return -1; - } - - return pfds[0].revents; + return res; #endif } @@ -303,11 +304,11 @@ static __inline__ int tdmv_api_readmsg_tdm(sng_fd_t fd, void *hdrbuf, int hdrlen 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, @@ -328,7 +329,7 @@ static __inline__ int tdmv_api_readmsg_tdm(sng_fd_t fd, void *hdrbuf, int hdrlen 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); @@ -384,7 +385,7 @@ static __inline__ int tdmv_api_writemsg_tdm(sng_fd_t fd, void *hdrbuf, int hdrle pri->data_length = datalen; memcpy(local_tx_data.data, databuf, pri->data_length); - if(!DeviceIoControl( + if (!DeviceIoControl( fd, IoctlWriteCommand, (LPVOID)&local_tx_data, @@ -406,18 +407,18 @@ static __inline__ int tdmv_api_writemsg_tdm(sng_fd_t fd, void *hdrbuf, int hdrle 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; diff --git a/libs/freetdm/src/include/zap_threadmutex.h b/libs/freetdm/src/include/zap_threadmutex.h index 9a9b336ed1..557f23ea51 100644 --- a/libs/freetdm/src/include/zap_threadmutex.h +++ b/libs/freetdm/src/include/zap_threadmutex.h @@ -31,7 +31,7 @@ zap_status_t zap_thread_create_detached(zap_thread_function_t func, void *data); 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); diff --git a/libs/freetdm/src/include/zap_types.h b/libs/freetdm/src/include/zap_types.h index d4ba2428db..9e189a138a 100644 --- a/libs/freetdm/src/include/zap_types.h +++ b/libs/freetdm/src/include/zap_types.h @@ -66,9 +66,9 @@ typedef enum { 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 { @@ -139,7 +139,7 @@ typedef struct zap_event zap_event_t; #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) diff --git a/libs/freetdm/src/openzap.c b/libs/freetdm/src/openzap.c index b10227bb63..3550fed880 100644 --- a/libs/freetdm/src/openzap.c +++ b/libs/freetdm/src/openzap.c @@ -42,6 +42,7 @@ static struct { zap_hash_t *interface_hash; + zap_mutex_t *mutex; } globals; static char *LEVEL_NAMES[] = { @@ -158,6 +159,7 @@ zap_status_t zap_span_create(zap_software_interface_t *zint, zap_span_t **span) 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; } @@ -165,6 +167,21 @@ zap_status_t zap_span_create(zap_software_interface_t *zint, zap_span_t **span) 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) { @@ -186,9 +203,13 @@ zap_status_t zap_span_add_channel(zap_span_t *span, zap_socket_t sockfd, zap_cha 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; } @@ -211,25 +232,33 @@ zap_status_t zap_span_find(const char *name, uint32_t id, zap_span_t **span) 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; @@ -247,7 +276,7 @@ zap_status_t zap_channel_open_any(const char *name, uint32_t span_id, zap_direct j = span_max; } - + zap_mutex_lock(globals.mutex); for(;;) { span = &zint->spans[j]; @@ -314,25 +343,60 @@ zap_status_t zap_channel_open_any(const char *name, uint32_t span_id, zap_direct } } + 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; @@ -347,25 +411,17 @@ zap_status_t zap_channel_close(zap_channel_t **zchan) 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; } @@ -405,6 +461,8 @@ static zap_status_t zchan_activate_dtmf_buffer(zap_channel_t *zchan) 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); @@ -413,6 +471,8 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo return ZAP_FAIL; } + zap_mutex_lock(zchan->span->mutex); + switch(command) { case ZAP_COMMAND_SET_INTERVAL: { @@ -424,7 +484,7 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo 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; @@ -432,7 +492,7 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo { 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; @@ -446,7 +506,7 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo 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; @@ -455,7 +515,7 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo { 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; @@ -468,10 +528,10 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo 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); } } } @@ -484,10 +544,10 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo 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); } } } @@ -495,7 +555,7 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo { 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; @@ -503,7 +563,7 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo { 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; @@ -513,10 +573,10 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo 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); } } } @@ -527,10 +587,10 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo 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); } } } @@ -538,16 +598,15 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo 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]))) { @@ -556,7 +615,7 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo } zchan->skip_read_frames = 200; - return ZAP_SUCCESS; + GOTO_STATUS(done, ZAP_SUCCESS); } } break; @@ -566,14 +625,18 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo 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); @@ -899,30 +962,39 @@ zap_status_t zap_channel_write(zap_channel_t *zchan, void *data, zap_size_t *dat 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"); @@ -942,8 +1014,11 @@ zap_status_t zap_global_init(void) 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++; @@ -967,16 +1042,21 @@ zap_status_t zap_global_init(void) 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; } diff --git a/libs/freetdm/src/testapp.c b/libs/freetdm/src/testapp.c index 8b9ae692ba..8160496c29 100644 --- a/libs/freetdm/src/testapp.c +++ b/libs/freetdm/src/testapp.c @@ -16,7 +16,8 @@ int main(int argc, char *argv[]) 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); @@ -42,7 +43,7 @@ int main(int argc, char *argv[]) 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) { diff --git a/libs/freetdm/src/zap_threadmutex.c b/libs/freetdm/src/zap_threadmutex.c index 8fc4632fd3..34e23bec5c 100644 --- a/libs/freetdm/src/zap_threadmutex.c +++ b/libs/freetdm/src/zap_threadmutex.c @@ -170,15 +170,17 @@ done: 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; } diff --git a/libs/freetdm/src/zap_wanpipe.c b/libs/freetdm/src/zap_wanpipe.c index 98325449e9..6386741e1f 100644 --- a/libs/freetdm/src/zap_wanpipe.c +++ b/libs/freetdm/src/zap_wanpipe.c @@ -346,14 +346,26 @@ static ZINT_WRITE_FUNCTION(wanpipe_write) 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; } @@ -362,16 +374,16 @@ static ZINT_WAIT_FUNCTION(wanpipe_wait) 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;