diff --git a/libs/openzap/src/include/openzap.h b/libs/openzap/src/include/openzap.h index 3e9d74a830..b47acfdbbe 100644 --- a/libs/openzap/src/include/openzap.h +++ b/libs/openzap/src/include/openzap.h @@ -73,10 +73,24 @@ #define ZAP_MAX_CHANNELS_SPAN 513 #define ZAP_MAX_SPANS_INTERFACE 33 +#ifdef WIN32 +#include +typedef HANDLE zap_socket_t; +#else typedef int zap_socket_t; +#endif + typedef size_t zap_size_t; struct zap_software_interface; +#define zap_true(expr)\ + (expr && ( !strcasecmp(expr, "yes") ||\ + !strcasecmp(expr, "on") ||\ + !strcasecmp(expr, "true") ||\ + !strcasecmp(expr, "enabled") ||\ + !strcasecmp(expr, "active") ||\ + atoi(expr))) ? 1 : 0 + #define zap_copy_string(x,y,z) strncpy(x, y, z - 1) /*! @@ -115,6 +129,8 @@ struct zap_software_interface; */ #define zap_safe_free(it) if (it) {free(it);it=NULL;} +#define zap_socket_close(it) if (it > -1) { close(it); it = -1;} + typedef enum { ZAP_SUCCESS, ZAP_FAIL, @@ -249,7 +265,6 @@ typedef struct zap_software_interface zap_software_interface_t; zap_status_t zap_span_create(zap_software_interface_t *zint, zap_span_t **span); 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_destroy(zap_span_t **span); 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); @@ -262,7 +277,9 @@ zap_status_t zap_global_init(void); zap_status_t zap_global_destroy(void); void zap_global_set_logger(zap_logger_t logger); void zap_global_set_default_logger(int level); - +unsigned zap_separate_string(char *buf, char delim, char **array, int arraylen); typedef struct hashtable zap_hash_t; - +typedef struct hashtable_itr zap_hash_itr_t; +typedef struct key zap_hash_key_t; +typedef struct value zap_hash_val_t; #endif diff --git a/libs/openzap/src/openzap.c b/libs/openzap/src/openzap.c index 58341cdef9..4644444811 100644 --- a/libs/openzap/src/openzap.c +++ b/libs/openzap/src/openzap.c @@ -108,6 +108,7 @@ static void default_logger(char *file, const char *func, int line, int level, ch } + zap_logger_t zap_log = null_logger; void zap_global_set_logger(zap_logger_t logger) @@ -174,6 +175,8 @@ zap_status_t zap_span_add_channel(zap_span_t *span, zap_socket_t sockfd, zap_cha new_chan->type = type; new_chan->sockfd = sockfd; new_chan->zint = span->zint; + new_chan->span_id = span->span_id; + new_chan->chan_id = span->chan_count; zap_set_flag(new_chan, ZAP_CHANNEL_CONFIGURED | ZAP_CHANNEL_READY); *chan = new_chan; return ZAP_SUCCESS; @@ -182,7 +185,6 @@ zap_status_t zap_span_add_channel(zap_span_t *span, zap_socket_t sockfd, zap_cha return ZAP_FAIL; } -zap_status_t zap_span_destroy(zap_span_t **span); zap_status_t zap_channel_open(const char *name, unsigned span_id, unsigned chan_id, zap_channel_t **zchan) { @@ -375,7 +377,6 @@ zap_status_t zap_global_init(void) zap_status_t zap_global_destroy(void) { - hashtable_destroy(globals.interface_hash, 1); #ifdef ZAP_ZT_SUPPORT zt_destroy(); @@ -383,5 +384,59 @@ zap_status_t zap_global_destroy(void) #ifdef ZAP_WANPIPE_SUPPORT wanpipe_destroy(); #endif + + hashtable_destroy(globals.interface_hash, 0); + return ZAP_SUCCESS; } + + +unsigned zap_separate_string(char *buf, char delim, char **array, int arraylen) +{ + int argc; + char *ptr; + int quot = 0; + char qc = '"'; + char *e; + int x; + + if (!buf || !array || !arraylen) { + return 0; + } + + memset(array, 0, arraylen * sizeof(*array)); + + ptr = buf; + + for (argc = 0; *ptr && (argc < arraylen - 1); argc++) { + array[argc] = ptr; + for (; *ptr; ptr++) { + if (*ptr == qc) { + if (quot) { + quot--; + } else { + quot++; + } + } else if ((*ptr == delim) && !quot) { + *ptr++ = '\0'; + break; + } + } + } + + if (*ptr) { + array[argc++] = ptr; + } + + /* strip quotes */ + for (x = 0; x < argc; x++) { + if (*(array[x]) == qc) { + (array[x])++; + if ((e = strchr(array[x], qc))) { + *e = '\0'; + } + } + } + + return argc; +} diff --git a/libs/openzap/src/testapp.c b/libs/openzap/src/testapp.c index c53bfed6f5..d760206313 100644 --- a/libs/openzap/src/testapp.c +++ b/libs/openzap/src/testapp.c @@ -2,8 +2,15 @@ int main(int argc, char *argv[]) { - printf("hello\n"); - zap_global_set_default_logger(ZAP_LOG_LEVEL_DEBUG); - zap_global_init(); + + if (zap_global_init() != ZAP_SUCCESS) { + fprintf(stderr, "Error loading OpenZAP\n"); + exit(-1); + } + + printf("OpenZAP loaded\n"); + sleep(2); + zap_global_destroy(); + } diff --git a/libs/openzap/src/zap_wanpipe.c b/libs/openzap/src/zap_wanpipe.c index 1552504560..d76b802988 100644 --- a/libs/openzap/src/zap_wanpipe.c +++ b/libs/openzap/src/zap_wanpipe.c @@ -70,6 +70,7 @@ typedef unsigned __int32 u_int32_t; #include #include #include +#include static zap_software_interface_t wanpipe_interface; @@ -78,12 +79,196 @@ struct wanpipe_channel { int x; }; + + +unsigned wp_open_lapd(zap_span_t *span, const char *name) +{ + struct wan_sockaddr_ll sa; + zap_socket_t sock = -1; + + errno = 0; + sock = socket(AF_WANPIPE, SOCK_RAW, 0); + memset(&sa,0,sizeof(struct wan_sockaddr_ll)); + + zap_log(ZAP_LOG_DEBUG, "attempting to open lapd device socket %s\n", name); + + if( sock < 0 ) { + zap_log(ZAP_LOG_ERROR, "socket error!\n"); + return 0; + } + + zap_copy_string(sa.sll_device, name, sizeof(sa.sll_device)); + zap_copy_string(sa.sll_card, "wanpipe1", sizeof(sa.sll_card)); + + sa.sll_protocol = htons(PVC_PROT); + sa.sll_family = AF_WANPIPE; + + if(bind(sock, (struct sockaddr *)&sa, sizeof(struct wan_sockaddr_ll)) < 0){ + zap_log(ZAP_LOG_ERROR, "socket bind error!\n"); + return 0; + } + + { + unsigned customer_id; + int err = ioctl(sock,SIOC_AFT_CUSTOMER_ID,&customer_id); + if (err){ + perror("Customer ID: "); + }else{ + printf("Customer ID 0x%X\n",customer_id); + return 1; + } + + + } + + + return 0; +} + + +static zap_socket_t wp_open_device(int span, int chan) +{ + char fname[256]; +#if defined(WIN32) + + _snprintf(fname , FNAME_LEN, "\\\\.\\WANPIPE%d_IF%d", span, chan - 1); + + return 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 + ); +#else + int fd=-1; + + sprintf(fname, "/dev/wptdm_s%dc%d", span, chan); + + fd = open(fname, O_RDWR); + + return fd; +#endif +} + +static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start, unsigned end, zap_chan_type_t type) +{ + unsigned configured = 0, x; + + for(x = start; x < end; x++) { + zap_channel_t *chan; + zap_socket_t sockfd = -1; + + sockfd = wp_open_device(spanno, x); + + if (sockfd > -1 && zap_span_add_channel(span, sockfd, type, &chan) == ZAP_SUCCESS) { + 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); + configured++; + } else { + zap_log(ZAP_LOG_ERROR, "failure configuring device s%dc%d\n", spanno, x); + } + } + + return configured; +} + +static unsigned wp_configure_channel(zap_config_t *cfg, const char *str, zap_span_t *span, zap_chan_type_t type) +{ + int items, i; + char *mydata, *item_list[10]; + char *sp, *ch, *mx; + int channo; + int spanno; + int top = 0; + int x; + unsigned configured = 0; + + assert(str != NULL); + + if (type == ZAP_CHAN_TYPE_DQ921) { + char *flag, *name; + + flag = str; + if ((name = strchr(flag, ':'))) { + name++; + } else { + name = flag; + flag = NULL; + } + + if (flag) { + if (strstr(flag, "q931")) { + type = ZAP_CHAN_TYPE_DQ931; + configured += wp_open_lapd(span, name); + return configured; + } + + } + } + + mydata = strdup(str); + assert(mydata != NULL); + + + items = zap_separate_string(mydata, ',', item_list, (sizeof(item_list) / sizeof(item_list[0]))); + + for(i = 0; i < items; i++) { + sp = item_list[i]; + if ((ch = strchr(sp, ':'))) { + *ch++ = '\0'; + } + + if (!(sp && ch)) { + zap_log(ZAP_LOG_ERROR, "Invalid input on line %d\n", cfg->lineno); + continue; + } + + + channo = atoi(ch); + spanno = atoi(sp); + + + if (channo < 0) { + zap_log(ZAP_LOG_ERROR, "Invalid channel number %d\n", channo); + continue; + } + + if (spanno < 0) { + zap_log(ZAP_LOG_ERROR, "Invalid span number %d\n", channo); + continue; + } + + if ((mx = strchr(ch, '-'))) { + mx++; + top = atoi(mx) + 1; + } else { + top = channo + 1; + } + + + if (top < 0) { + zap_log(ZAP_LOG_ERROR, "Invalid range number %d\n", top); + continue; + } + + configured += wp_open_range(span, spanno, channo, top, type); + + } + + free(mydata); + + return configured; +} + static ZINT_CONFIGURE_FUNCTION(wanpipe_configure) { zap_config_t cfg; char *var, *val; int catno = -1; zap_span_t *span = NULL; + int new_span = 0; + unsigned configured = 0, d = 0; ZINT_CONFIGURE_MUZZLE; @@ -95,28 +280,52 @@ static ZINT_CONFIGURE_FUNCTION(wanpipe_configure) while (zap_config_next_pair(&cfg, &var, &val)) { if (!strcasecmp(cfg.category, "span")) { if (cfg.catno != catno) { - zap_log(ZAP_LOG_DEBUG, "found config for span %d\n", cfg.catno); + zap_log(ZAP_LOG_DEBUG, "found config for span\n"); catno = cfg.catno; - if (zap_span_create(&wanpipe_interface, &span) == ZAP_SUCCESS) { - zap_log(ZAP_LOG_DEBUG, "created span %d\n", span->span_id); - } else { - zap_log(ZAP_LOG_CRIT, "failure creating span\n"); - span = NULL; - } - - continue; + new_span = 1; + span = NULL; } + if (new_span) { + if (!strcasecmp(var, "enabled") && ! zap_true(val)) { + zap_log(ZAP_LOG_DEBUG, "span (disabled)\n"); + } else { + if (zap_span_create(&wanpipe_interface, &span) == ZAP_SUCCESS) { + zap_log(ZAP_LOG_DEBUG, "created span %d\n", span->span_id); + } else { + zap_log(ZAP_LOG_CRIT, "failure creating span\n"); + span = NULL; + } + } + new_span = 0; + continue; + } + if (!span) { continue; } 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"); + } else if (!strcasecmp(var, "b-channel")) { + configured += wp_configure_channel(&cfg, val, span, ZAP_CHAN_TYPE_B); + } else if (!strcasecmp(var, "d-channel")) { + if (d) { + zap_log(ZAP_LOG_WARNING, "ignoring extra d-channel\n"); + } else { + configured += wp_configure_channel(&cfg, val, span, ZAP_CHAN_TYPE_DQ921); + d++; + } + } } } zap_config_close_file(&cfg); - return ZAP_FAIL; + zap_log(ZAP_LOG_INFO, "wanpipe configured %u channel(s)\n", configured); + + return configured ? ZAP_SUCCESS : ZAP_FAIL; } static ZINT_OPEN_FUNCTION(wanpipe_open) @@ -182,5 +391,23 @@ zap_status_t wanpipe_init(zap_software_interface_t **zint) zap_status_t wanpipe_destroy(void) { - return ZAP_FAIL; + int i,j; + + for(i = 1; i <= wanpipe_interface.span_index; i++) { + zap_span_t *cur_span = &wanpipe_interface.spans[i]; + + if (zap_test_flag(cur_span, ZAP_SPAN_CONFIGURED)) { + for(j = 1; j <= cur_span->chan_count; j++) { + zap_channel_t *cur_chan = &cur_span->channels[j]; + if (zap_test_flag(cur_chan, ZAP_CHANNEL_CONFIGURED)) { + zap_log(ZAP_LOG_INFO, "Closing channel %u:%u fd:%d\n", cur_chan->span_id, cur_chan->chan_id, cur_chan->sockfd); + zap_socket_close(cur_chan->sockfd); + } + } + } + } + + memset(&wanpipe_interface, 0, sizeof(wanpipe_interface)); + + return ZAP_SUCCESS; }