diff --git a/libs/freetdm/src/include/openzap.h b/libs/freetdm/src/include/openzap.h index 61981dd9fb..36f47bd290 100644 --- a/libs/freetdm/src/include/openzap.h +++ b/libs/freetdm/src/include/openzap.h @@ -95,37 +95,37 @@ struct zap_software_interface; /*! \brief Test for the existance of a flag on an arbitary object - \param obj the object to test - \param flag the or'd list of flags to test + \command obj the object to test + \command flag the or'd list of flags to test \return true value if the object has the flags defined */ #define zap_test_flag(obj, flag) ((obj)->flags & flag) /*! \brief Set a flag on an arbitrary object - \param obj the object to set the flags on - \param flag the or'd list of flags to set + \command obj the object to set the flags on + \command flag the or'd list of flags to set */ #define zap_set_flag(obj, flag) (obj)->flags |= (flag) /*! \brief Clear a flag on an arbitrary object while locked - \param obj the object to test - \param flag the or'd list of flags to clear + \command obj the object to test + \command flag the or'd list of flags to clear */ #define zap_clear_flag(obj, flag) (obj)->flags &= ~(flag) /*! \brief Copy flags from one arbitrary object to another - \param dest the object to copy the flags to - \param src the object to copy the flags from - \param flags the flags to copy + \command dest the object to copy the flags to + \command src the object to copy the flags from + \command flags the flags to copy */ #define zap_copy_flags(dest, src, flags) (dest)->flags &= ~(flags); (dest)->flags |= ((src)->flags & (flags)) /*! \brief Free a pointer and set it to NULL unless it already is NULL - \param it the pointer + \command it the pointer */ #define zap_safe_free(it) if (it) {free(it);it=NULL;} @@ -134,14 +134,15 @@ struct zap_software_interface; typedef enum { ZAP_SUCCESS, ZAP_FAIL, - ZAP_MEMERR + ZAP_MEMERR, + ZAP_TIMEOUT } zap_status_t; typedef enum { + ZAP_NO_FLAGS = 0, ZAP_READ = (1 << 0), ZAP_WRITE = (1 << 1), - ZAP_ERROR = (1 << 2), - ZAP_EVENT = (1 << 3) + ZAP_ERROR = (1 << 2) } zap_wait_flag_t; typedef enum { @@ -150,6 +151,11 @@ typedef enum { ZAP_CODEC_SLIN = 10 } zap_codec_t; +typedef enum { + ZAP_COMMAND_SET_INTERVAL, + ZAP_COMMAND_GET_INTERVAL +} zap_command_t; + typedef enum { ZAP_SPAN_CONFIGURED = (1 << 0), ZAP_SPAN_READY = (1 << 1) @@ -192,17 +198,15 @@ typedef struct zap_span zap_span_t; #define ZINT_CONFIGURE_ARGS (struct zap_software_interface *zint) #define ZINT_OPEN_ARGS (zap_channel_t *zchan) #define ZINT_CLOSE_ARGS (zap_channel_t *zchan) -#define ZINT_SET_CODEC_ARGS (zap_channel_t *zchan, zap_codec_t codec) -#define ZINT_SET_INTERVAL_ARGS (zap_channel_t *zchan, unsigned ms) -#define ZINT_WAIT_ARGS (zap_channel_t *zchan, zap_wait_flag_t flags, unsigned to) +#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, unsigned 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) typedef zap_status_t (*zint_configure_t) ZINT_CONFIGURE_ARGS ; typedef zap_status_t (*zint_open_t) ZINT_OPEN_ARGS ; typedef zap_status_t (*zint_close_t) ZINT_CLOSE_ARGS ; -typedef zap_status_t (*zint_set_codec_t) ZINT_SET_CODEC_ARGS ; -typedef zap_status_t (*zint_set_interval_t) ZINT_SET_INTERVAL_ARGS ; +typedef zap_status_t (*zint_command_t) ZINT_COMMAND_ARGS ; typedef zap_status_t (*zint_wait_t) ZINT_WAIT_ARGS ; typedef zap_status_t (*zint_read_t) ZINT_READ_ARGS ; typedef zap_status_t (*zint_write_t) ZINT_WRITE_ARGS ; @@ -210,17 +214,15 @@ typedef zap_status_t (*zint_write_t) ZINT_WRITE_ARGS ; #define ZINT_CONFIGURE_FUNCTION(name) zap_status_t name ZINT_CONFIGURE_ARGS #define ZINT_OPEN_FUNCTION(name) zap_status_t name ZINT_OPEN_ARGS #define ZINT_CLOSE_FUNCTION(name) zap_status_t name ZINT_CLOSE_ARGS -#define ZINT_SET_CODEC_FUNCTION(name) zap_status_t name ZINT_SET_CODEC_ARGS -#define ZINT_SET_INTERVAL_FUNCTION(name) zap_status_t name ZINT_SET_INTERVAL_ARGS +#define ZINT_COMMAND_FUNCTION(name) zap_status_t name ZINT_COMMAND_ARGS #define ZINT_WAIT_FUNCTION(name) zap_status_t name ZINT_WAIT_ARGS #define ZINT_READ_FUNCTION(name) zap_status_t name ZINT_READ_ARGS #define ZINT_WRITE_FUNCTION(name) zap_status_t name ZINT_WRITE_ARGS #define ZINT_CONFIGURE_MUZZLE assert(zint != NULL) -#define ZINT_OPEN_MUZZLEE assert(zchan != NULL) +#define ZINT_OPEN_MUZZLE assert(zchan != NULL) #define ZINT_CLOSE_MUZZLE assert(zchan != NULL) -#define ZINT_SET_CODEC_MUZZLE assert(zchan != NULL); assert(codec != 0) -#define ZINT_SET_INTERVAL_MUZZLE assert(zchan != NULL); assert(ms != 0) +#define ZINT_COMMAND_MUZZLE assert(zchan != NULL); assert(command != 0); assert(obj != NULL) #define ZINT_WAIT_MUZZLE assert(zchan != NULL); assert(flags != 0); assert(to != 0) #define ZINT_READ_MUZZLE assert(zchan != NULL); assert(data != NULL); assert(datalen != NULL) #define ZINT_WRITE_MUZZLE assert(zchan != NULL); assert(data != NULL); assert(datalen != NULL) @@ -253,8 +255,7 @@ struct zap_software_interface { zint_configure_t configure; zint_open_t open; zint_close_t close; - zint_set_codec_t set_codec; - zint_set_interval_t set_interval; + zint_command_t command; zint_wait_t wait; zint_read_t read; zint_write_t write; @@ -269,9 +270,8 @@ zap_status_t zap_span_add_channel(zap_span_t *span, zap_socket_t sockfd, zap_cha zap_status_t zap_channel_open(const char *name, unsigned span_id, unsigned chan_id, zap_channel_t **zchan); zap_status_t zap_channel_close(zap_channel_t **zchan); -zap_status_t zap_channel_set_codec(zap_channel_t *zchan, zap_codec_t codec); -zap_status_t zap_channel_set_interval(zap_channel_t *zchan, unsigned ms); -zap_status_t zap_channel_wait(zap_channel_t *zchan, zap_wait_flag_t flags, unsigned to); +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, unsigned 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/openzap.c b/libs/freetdm/src/openzap.c index 8f3383b759..dbb831b3e1 100644 --- a/libs/freetdm/src/openzap.c +++ b/libs/freetdm/src/openzap.c @@ -229,24 +229,7 @@ zap_status_t zap_channel_close(zap_channel_t **zchan) } -zap_status_t zap_channel_set_codec(zap_channel_t *zchan, zap_codec_t codec) -{ - assert(zchan != NULL); - assert(zchan->zint != NULL); - - if (!zap_test_flag(zchan, ZAP_CHANNEL_OPEN)) { - return ZAP_FAIL; - } - - if (!zchan->zint->set_codec) { - return ZAP_FAIL; - } - - return zchan->zint->set_codec(zchan, codec); - -} - -zap_status_t zap_channel_set_interval(zap_channel_t *zchan, unsigned ms) +zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, void *obj) { assert(zchan != NULL); assert(zchan->zint != NULL); @@ -255,15 +238,15 @@ zap_status_t zap_channel_set_interval(zap_channel_t *zchan, unsigned ms) return ZAP_FAIL; } - if (!zchan->zint->set_interval) { + if (!zchan->zint->command) { return ZAP_FAIL; } - return zchan->zint->set_interval(zchan, ms); + return zchan->zint->command(zchan, command, obj); } -zap_status_t zap_channel_wait(zap_channel_t *zchan, zap_wait_flag_t flags, unsigned to) +zap_status_t zap_channel_wait(zap_channel_t *zchan, zap_wait_flag_t *flags, unsigned to) { assert(zchan != NULL); assert(zchan->zint != NULL); @@ -286,7 +269,7 @@ zap_status_t zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *data assert(zchan != NULL); assert(zchan->zint != NULL); assert(zchan->zint != NULL); - + if (!zap_test_flag(zchan, ZAP_CHANNEL_OPEN)) { return ZAP_FAIL; } diff --git a/libs/freetdm/src/zap_wanpipe.c b/libs/freetdm/src/zap_wanpipe.c index a165afea70..a7412eab8a 100644 --- a/libs/freetdm/src/zap_wanpipe.c +++ b/libs/freetdm/src/zap_wanpipe.c @@ -236,7 +236,7 @@ static ZINT_CONFIGURE_FUNCTION(wanpipe_configure) zap_log(ZAP_LOG_DEBUG, "span %d [%s]=[%s]\n", span->span_id, var, val); if (!strcasecmp(var, "enabled")) { - zap_log(ZAP_LOG_WARNING, "'enabled' param ignored when it's not the first param in a [span]\n"); + zap_log(ZAP_LOG_WARNING, "'enabled' command ignored when it's not the first command in a [span]\n"); } else if (!strcasecmp(var, "b-channel")) { configured += wp_configure_channel(&cfg, val, span, ZAP_CHAN_TYPE_B); } else if (!strcasecmp(var, "d-channel")) { @@ -266,42 +266,185 @@ static ZINT_CONFIGURE_FUNCTION(wanpipe_configure) static ZINT_OPEN_FUNCTION(wanpipe_open) { ZINT_OPEN_MUZZLE; - return ZAP_FAIL; + return ZAP_SUCCESS; } static ZINT_CLOSE_FUNCTION(wanpipe_close) { ZINT_CLOSE_MUZZLE; - return ZAP_FAIL; + return ZAP_SUCCESS; } -static ZINT_SET_CODEC_FUNCTION(wanpipe_set_codec) +static ZINT_COMMAND_FUNCTION(wanpipe_command) { - ZINT_SET_CODEC_MUZZLE; - return ZAP_FAIL; -} + wanpipe_tdm_api_t tdm_api; + int err; -static ZINT_SET_INTERVAL_FUNCTION(wanpipe_set_interval) -{ - ZINT_SET_INTERVAL_MUZZLE; - return ZAP_FAIL; + ZINT_COMMAND_MUZZLE; + + memset(&tdm_api, 0, sizeof(tdm_api)); + + switch(command) { + case ZAP_COMMAND_GET_INTERVAL: + { + tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_GET_USR_PERIOD; + + if (!(err = sangoma_tdm_cmd_exec(zchan->sockfd, tdm_api))) { + *((int *)obj) = tdm_api.wp_tdm_cmd.usr_period; + } + + } + 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 = *((int *)obj); + err = sangoma_tdm_cmd_exec(zchan->sockfd, tdm_api); + } + break; + }; + + return err ? ZAP_FAIL : ZAP_SUCCESS; } static ZINT_WAIT_FUNCTION(wanpipe_wait) { + fd_set read_fds, write_fds, error_fds, *r = NULL, *w = NULL, *e = NULL; + zap_wait_flag_t inflags = *flags; + int s; + struct timeval tv, *tvp = NULL; + ZINT_WAIT_MUZZLE; - return ZAP_FAIL; + + if (to) { + memset(&tv, 0, sizeof(tv)); + tv.tv_sec = to / 1000; + tv.tv_usec = (to % 1000) * 1000; + tvp = &tv; + } + + FD_ZERO(&read_fds); + FD_ZERO(&write_fds); + FD_ZERO(&error_fds); + + + if (inflags & ZAP_READ) { + r = &read_fds; + FD_SET(zchan->sockfd, r); + } + + if (inflags & ZAP_WRITE) { + w = &write_fds; + FD_SET(zchan->sockfd, w); + } + + if (inflags & ZAP_ERROR) { + e = &error_fds; + FD_SET(zchan->sockfd, e); + } + + *flags = ZAP_NO_FLAGS; + s = select(zchan->sockfd + 1, r, w, e, tvp); + + if (s < 0) { + return ZAP_FAIL; + } + + if (s > 0) { + if (r && FD_ISSET(zchan->sockfd, r)) { + *flags |= ZAP_READ; + } + + if (w && FD_ISSET(zchan->sockfd, w)) { + *flags |= ZAP_WRITE; + } + + if (e && FD_ISSET(zchan->sockfd, e)) { + *flags |= ZAP_ERROR; + } + } + + if (s == 0) { + return ZAP_TIMEOUT; + } + +} + +static ZINT_READ_FUNCTION(wanpipe_read_unix) +{ + int rx_len = 0; + struct msghdr msg; + struct iovec iov[2]; + wp_tdm_api_rx_hdr_t hdrframe; + + memset(&msg, 0, sizeof(struct msghdr)); + + iov[0].iov_len = sizeof(hdrframe); + iov[0].iov_base = &hdrframe; + + iov[1].iov_len = *datalen; + iov[1].iov_base = data; + + msg.msg_iovlen = 2; + msg.msg_iov = iov; + + rx_len = read(zchan->sockfd, &msg, iov[1].iov_len + sizeof(hdrframe)); + + if (rx_len <= sizeof(hdrframe)) { + return ZAP_FAIL; + } + + rx_len -= sizeof(hdrframe); + *datalen = rx_len; + + return ZAP_SUCCESS; } static ZINT_READ_FUNCTION(wanpipe_read) { ZINT_READ_MUZZLE; + +#ifndef WIN32 + return wanpipe_read_unix(zchan, data, datalen); +#endif + return ZAP_FAIL; } +static ZINT_WRITE_FUNCTION(wanpipe_write_unix) +{ + int bsent; + struct msghdr msg; + struct iovec iov[2]; + wp_tdm_api_rx_hdr_t hdrframe; + + memset(&msg, 0, sizeof(struct msghdr)); + + iov[0].iov_len = sizeof(hdrframe); + iov[0].iov_base = &hdrframe; + + iov[1].iov_len = *datalen; + iov[1].iov_base = data; + + msg.msg_iovlen = 2; + msg.msg_iov = iov; + + bsent = write(zchan->sockfd, &msg, iov[1].iov_len + sizeof(hdrframe)); + + if (bsent > 0){ + bsent -= sizeof(wp_tdm_api_tx_hdr_t); + } + +} + static ZINT_WRITE_FUNCTION(wanpipe_write) { ZINT_WRITE_MUZZLE; + +#ifndef WIN32 + return wanpipe_write_unix(zchan, data, datalen); +#endif + return ZAP_FAIL; } @@ -314,8 +457,7 @@ zap_status_t wanpipe_init(zap_software_interface_t **zint) wanpipe_interface.configure = wanpipe_configure; wanpipe_interface.open = wanpipe_open; wanpipe_interface.close = wanpipe_close; - wanpipe_interface.set_codec = wanpipe_set_codec; - wanpipe_interface.set_interval = wanpipe_set_interval; + wanpipe_interface.command = wanpipe_command; wanpipe_interface.wait = wanpipe_wait; wanpipe_interface.read = wanpipe_read; wanpipe_interface.write = wanpipe_write;