From eb0262ddc084d8abaa1379cf0c62d63a33b77897 Mon Sep 17 00:00:00 2001
From: Michael Jerris <mike@jerris.com>
Date: Fri, 18 May 2007 05:33:19 +0000
Subject: [PATCH] step towards building on windows again.

git-svn-id: http://svn.openzap.org/svn/openzap/trunk@27 a93c3328-9c30-0410-af19-c9cd2b2d52af
---
 libs/freetdm/openzap.vcproj                   |  40 +-
 libs/freetdm/src/include/openzap.h            |  20 +-
 .../freetdm/src/include/zap_wanpipe_windows.h | 363 ++++++++++++++++++
 libs/freetdm/src/zap_wanpipe.c                |  65 ++--
 4 files changed, 454 insertions(+), 34 deletions(-)
 create mode 100644 libs/freetdm/src/include/zap_wanpipe_windows.h

diff --git a/libs/freetdm/openzap.vcproj b/libs/freetdm/openzap.vcproj
index 2cae0acfce..bdcaead122 100644
--- a/libs/freetdm/openzap.vcproj
+++ b/libs/freetdm/openzap.vcproj
@@ -20,7 +20,7 @@
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
 			ConfigurationType="4"
-			CharacterSet="1"
+			CharacterSet="2"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
@@ -87,7 +87,7 @@
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
 			ConfigurationType="4"
-			CharacterSet="1"
+			CharacterSet="2"
 			WholeProgramOptimization="1"
 			>
 			<Tool
@@ -187,6 +187,22 @@
 			<File
 				RelativePath=".\src\zap_skel.c"
 				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
 			</File>
 			<File
 				RelativePath=".\src\zap_wanpipe.c"
@@ -211,6 +227,22 @@
 			<File
 				RelativePath=".\src\zap_zt.c"
 				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
 			</File>
 		</Filter>
 		<Filter
@@ -266,6 +298,10 @@
 				RelativePath=".\src\include\zap_wanpipe.h"
 				>
 			</File>
+			<File
+				RelativePath=".\src\include\zap_wanpipe_windows.h"
+				>
+			</File>
 			<File
 				RelativePath=".\src\include\zap_zt.h"
 				>
diff --git a/libs/freetdm/src/include/openzap.h b/libs/freetdm/src/include/openzap.h
index 5626df6adc..4ee1e3a6fe 100644
--- a/libs/freetdm/src/include/openzap.h
+++ b/libs/freetdm/src/include/openzap.h
@@ -36,6 +36,19 @@
 
 #define _XOPEN_SOURCE 500
 
+#ifndef HAVE_STRINGS_H
+#define HAVE_STRINGS_H 1
+#endif
+#ifndef HAVE_SYS_SOCKET_H
+#define HAVE_SYS_SOCKET_H 1
+#endif
+
+#ifndef __WINDOWS__
+#if defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)
+#define __WINDOWS__
+#endif
+#endif
+
 #ifdef _MSC_VER
 #if (_MSC_VER >= 1400)			/* VC8+ */
 #ifndef _CRT_SECURE_NO_DEPRECATE
@@ -51,12 +64,17 @@
 #ifndef snprintf
 #define snprintf _snprintf
 #endif
+#undef HAVE_STRINGS_H
+#undef HAVE_SYS_SOCKET_H
+/* disable warning for zero length array in a struct */
+/* this will cause errors on c99 and ansi compliant compilers and will need to be fixed in the wanpipe header files */
+#pragma warning(disable:4706)
 #endif
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#ifndef _MSC_VER
+#ifdef HAVE_STRINGS_H
 #include <strings.h>
 #endif
 #include <assert.h>
diff --git a/libs/freetdm/src/include/zap_wanpipe_windows.h b/libs/freetdm/src/include/zap_wanpipe_windows.h
new file mode 100644
index 0000000000..d5773da640
--- /dev/null
+++ b/libs/freetdm/src/include/zap_wanpipe_windows.h
@@ -0,0 +1,363 @@
+/*****************************************************************************
+ * win_api_common.h	Windows Sangoma API Code Library
+ *
+ * Author(s):	David Rokhvarg <davidr@sangoma.com>
+ *
+ * Copyright:	(c) 1984-2006 Sangoma Technologies Inc.
+ *
+ * ============================================================================
+ */
+
+#ifndef _WIN_API_COMMON_H
+#define _WIN_API_COMMON_H
+
+#define DEV_NAME_LEN	100
+char device_name[DEV_NAME_LEN];
+
+/* IOCTL management structures and variables*/
+wan_udp_hdr_t	wan_udp;
+
+static wan_cmd_api_t api_cmd;
+static api_tx_hdr_t *tx_hdr = (api_tx_hdr_t *)api_cmd.data;
+
+/* keeps the LAST (and single) event received */
+static wp_tdm_api_rx_hdr_t last_tdm_api_event_buffer;
+
+static 
+int 
+tdmv_api_ioctl(
+	HANDLE fd, 
+	wanpipe_tdm_api_cmd_t *tdm_api_cmd
+	)
+{
+	DWORD			ln;
+    unsigned char	id = 0;
+	int				err = 0;
+
+	wan_udp.wan_udphdr_request_reply = 0x01;
+	wan_udp.wan_udphdr_id			 = id;
+   	wan_udp.wan_udphdr_return_code	 = WAN_UDP_TIMEOUT_CMD;
+
+	wan_udp.wan_udphdr_command	= WAN_TDMV_API_IOCTL;
+	wan_udp.wan_udphdr_data_len	= sizeof(wanpipe_tdm_api_cmd_t);
+
+	//copy data from caller's buffer to driver's buffer
+	memcpy(	wan_udp.wan_udphdr_data, 
+			(void*)tdm_api_cmd,
+			sizeof(wanpipe_tdm_api_cmd_t));
+
+	if(DeviceIoControl(
+			fd,
+			IoctlManagementCommand,
+			(LPVOID)&wan_udp,
+			sizeof(wan_udp_hdr_t),
+			(LPVOID)&wan_udp,
+			sizeof(wan_udp_hdr_t),
+			(LPDWORD)(&ln),
+			(LPOVERLAPPED)NULL
+			) == FALSE){
+		//actual ioctl failed
+		err = 1;
+		return err;
+	}else{
+		err = 0;
+	}
+
+	if(wan_udp.wan_udphdr_return_code != WAN_CMD_OK){
+		//ioctl ok, but command failed
+		return 2;
+	}
+
+	//copy data from driver's buffer to caller's buffer
+	memcpy(	(void*)tdm_api_cmd,
+			wan_udp.wan_udphdr_data, 
+			sizeof(wanpipe_tdm_api_cmd_t));
+	return 0;
+}
+
+static 
+int 
+wanpipe_api_ioctl(
+	HANDLE fd,
+	wan_cmd_api_t *api_cmd
+	)
+{
+	DWORD			ln;
+    unsigned char	id = 0;
+	int				err = 0;
+
+	wan_udp.wan_udphdr_request_reply = 0x01;
+	wan_udp.wan_udphdr_id			 = id;
+   	wan_udp.wan_udphdr_return_code   = WAN_UDP_TIMEOUT_CMD;
+
+	wan_udp.wan_udphdr_command	= SIOC_WANPIPE_API;
+	wan_udp.wan_udphdr_data_len	= sizeof(wan_cmd_api_t);
+
+	//copy data from caller's buffer to driver's buffer
+	memcpy(	wan_udp.wan_udphdr_data, 
+			(void*)api_cmd,
+			sizeof(wan_cmd_api_t));
+
+	if(DeviceIoControl(
+			fd,
+			IoctlManagementCommand,
+			(LPVOID)&wan_udp,
+			sizeof(wan_udp_hdr_t),
+			(LPVOID)&wan_udp,
+			sizeof(wan_udp_hdr_t),
+			(LPDWORD)(&ln),
+			(LPOVERLAPPED)NULL
+			) == FALSE){
+		err = 1;
+		return err;
+	}else{
+		err = 0;
+	}
+
+	if(wan_udp.wan_udphdr_return_code != WAN_CMD_OK){
+		return 2;
+	}
+
+	//copy data from driver's buffer to caller's buffer
+	memcpy(	(void*)api_cmd,
+			wan_udp.wan_udphdr_data, 
+			sizeof(wan_cmd_api_t));
+	return 0;
+}
+
+// Blocking read command. If used after DoApiPollCommand(),
+// it will return immediatly, without blocking.
+static 
+USHORT 
+DoReadCommand(
+	HANDLE drv, 
+	RX_DATA_STRUCT * pRx
+	)
+{
+	DWORD ln;
+
+	if (DeviceIoControl(
+			drv,
+			IoctlReadCommand,
+			(LPVOID)NULL,
+			0L,
+			(LPVOID)pRx,
+			sizeof(RX_DATA_STRUCT),
+			(LPDWORD)(&ln),
+			(LPOVERLAPPED)NULL
+			) == FALSE){
+		//check messages log
+		return 1;
+	}else{
+		return 0;
+	}
+}
+
+// Blocking write command. If used after DoApiPollCommand(),
+// it will return immediatly, without blocking.
+static
+UCHAR 
+DoWriteCommand(
+	HANDLE drv, 
+	TX_DATA_STRUCT * pTx
+	)
+{
+	DWORD ln;
+
+	if(DeviceIoControl(
+			drv,
+			IoctlWriteCommand,
+			(LPVOID)pTx,
+			(ULONG)sizeof(TX_DATA_STRUCT),
+			(LPVOID)pTx,
+			sizeof(TX_DATA_STRUCT),
+			(LPDWORD)(&ln),
+			(LPOVERLAPPED)NULL
+			) == FALSE){
+		return 1;
+	}else{
+		return 0;
+	}
+}
+
+// Blocking API Poll command.
+static
+USHORT 
+DoApiPollCommand(
+	HANDLE drv, 
+	API_POLL_STRUCT *api_poll_ptr
+	)
+{
+	DWORD ln;
+
+	if (DeviceIoControl(
+			drv,
+			IoctlApiPoll,
+			(LPVOID)NULL,
+			0L,
+			(LPVOID)api_poll_ptr,
+			sizeof(API_POLL_STRUCT),
+			(LPDWORD)(&ln),
+			(LPOVERLAPPED)NULL
+						) == FALSE){
+		return 1;
+	}else{
+		return 0;
+	}
+}
+
+static
+int 
+DoManagementCommand(
+	HANDLE drv, 
+	wan_udp_hdr_t* wan_udp
+	)
+{
+	DWORD ln;
+    static unsigned char id = 0;
+
+	wan_udp->wan_udphdr_request_reply = 0x01;
+	wan_udp->wan_udphdr_id = id++;
+   	wan_udp->wan_udphdr_return_code = WAN_UDP_TIMEOUT_CMD;
+
+	if(DeviceIoControl(
+			drv,
+			IoctlManagementCommand,
+			(LPVOID)wan_udp,
+			sizeof(wan_udp_hdr_t),
+			(LPVOID)wan_udp,
+			sizeof(wan_udp_hdr_t),
+			(LPDWORD)(&ln),
+			(LPOVERLAPPED)NULL
+						) == FALSE){
+		return 1;
+	}else{
+		return 0;
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+//structures and definitions used for queueing data
+//
+typedef struct
+{
+	void*				previous;
+	TX_RX_DATA_STRUCT	tx_rx_data;
+}api_queue_element_t;
+
+#define API_Q_MUTEX_TIMEOUT	1000//1 second
+#define API_Q_MAX_SIZE		100//optimal length. for short data may need longer queue
+
+enum API_Q_STATUS{
+	API_Q_SUCCESS=0,
+	API_Q_GEN_FAILURE,
+	API_Q_MEM_ALLOC_FAILURE,
+	API_Q_FULL,
+	API_Q_EMPTY
+};
+
+typedef struct
+{
+	//number of nodes in the list
+	USHORT size;
+	//insert at tail
+	api_queue_element_t * tail;
+	//remove from head
+	api_queue_element_t * head;
+	//mutex for synchronizing access to the queue
+	HANDLE api_queue_mutex;
+}api_queue_t;
+
+
+static __inline int api_enqueue(	api_queue_t* api_queue, 
+									unsigned char * buffer,
+									unsigned short length)
+{
+	api_queue_element_t *element;
+	DWORD				mresult;
+
+	mresult = WaitForSingleObject(api_queue->api_queue_mutex, API_Q_MUTEX_TIMEOUT);
+	if (mresult != WAIT_OBJECT_0) {
+		return API_Q_GEN_FAILURE;
+	}
+
+	if(api_queue->size == API_Q_MAX_SIZE){
+		ReleaseMutex(api_queue->api_queue_mutex);
+		return API_Q_FULL;
+	}
+
+	element = malloc(sizeof(api_queue_element_t));
+	if(element == NULL){
+		ReleaseMutex(api_queue->api_queue_mutex);
+		return API_Q_MEM_ALLOC_FAILURE;
+	}
+
+	//now copy everything in to the element
+	memcpy(element->tx_rx_data.data, buffer, length);
+	
+	element->tx_rx_data.api_header.data_length = length;
+	element->tx_rx_data.api_header.operation_status = SANG_STATUS_TX_TIMEOUT;
+
+	//insert element at the tail of the queue
+	element->previous = NULL;
+
+	if(api_queue->size == 0){
+		//special case of a previously empty queue
+		api_queue->head = element;
+		api_queue->tail = element;
+	}else{
+		api_queue->tail->previous = element;
+		api_queue->tail = element;
+	}
+	api_queue->size++;
+	ReleaseMutex(api_queue->api_queue_mutex);
+	return API_Q_SUCCESS;
+}
+
+static __inline int api_dequeue(	api_queue_t* api_queue,
+											TX_RX_DATA_STRUCT* destination)
+{
+	api_queue_element_t *element;
+	DWORD				mresult;
+
+	mresult = WaitForSingleObject(api_queue->api_queue_mutex, API_Q_MUTEX_TIMEOUT);
+	if (mresult != WAIT_OBJECT_0) {
+		return API_Q_GEN_FAILURE;
+	}
+
+	if(api_queue->size == 0){
+		//tx queue is empty
+		ReleaseMutex(api_queue->api_queue_mutex);
+		return API_Q_EMPTY;
+	}
+
+	//remove from the head of the queue
+	element = api_queue->head;
+	api_queue->head = element->previous;
+
+	//now copy everything in to the user buffer
+	memcpy(destination, &element->tx_rx_data, sizeof(TX_DATA_STRUCT));
+
+	free(element);
+	api_queue->size--;
+	if(api_queue->size == 0){
+		api_queue->head = NULL;
+		api_queue->tail = NULL;
+	}
+	ReleaseMutex(api_queue->api_queue_mutex);
+	return API_Q_SUCCESS;
+}
+
+//remove all elements from the queue
+static __inline void empty_api_queue(api_queue_t* api_queue)
+{
+	TX_DATA_STRUCT tx_rx_data;
+
+	while(api_dequeue(api_queue, &tx_rx_data) == 0){
+		;
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////
+#endif /* _WIN_API_COMMON_H */
diff --git a/libs/freetdm/src/zap_wanpipe.c b/libs/freetdm/src/zap_wanpipe.c
index 53ce0cc9d0..55c037d25a 100644
--- a/libs/freetdm/src/zap_wanpipe.c
+++ b/libs/freetdm/src/zap_wanpipe.c
@@ -33,12 +33,6 @@
 
 #define WANPIPE_TDM_API 1
 
-#ifndef __WINDOWS__
-#if defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)
-#define __WINDOWS__
-#endif
-#endif
-
 #include "openzap.h"
 #include "zap_wanpipe.h"
 
@@ -49,28 +43,30 @@
 #pragma warning(disable:4200 4201 4214)
 #endif
 #include <windows.h>
-#include <winioctl.h>
-#include <conio.h>
-#include <stddef.h>
-typedef unsigned __int16 u_int16_t;
-typedef unsigned __int32 u_int32_t;
+#define FNAME_LEN	50
+#define WP_INVALID_SOCKET INVALID_HANDLE_VALUE
+#else
+#define WP_INVALID_SOCKET -1
 #endif
 
 #include <wanpipe_defines.h>
 #include <wanpipe_cfg.h>
 #include <wanpipe_tdm_api.h>
+#include <sdla_te1_pmc.h>
 #ifdef __WINDOWS__
 #include <sang_status_defines.h>
 #include <sang_api.h>
 #endif
-#include <sdla_te1_pmc.h>
-#include <sdla_te1.h>
-#include <sdla_56k.h>
-#include <sdla_remora.h>
-#include <sdla_te3.h>	
-#include <sdla_front_end.h>
 #include <sdla_aft_te1.h>
+
+#ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
+#endif
+
+#if defined(__WINDOWS__)
+#include <zap_wanpipe_windows.h>
+#endif
+
 
 static zap_software_interface_t wanpipe_interface;
 
@@ -96,6 +92,10 @@ static zap_socket_t wp_open_device(int span, int chan)
 
 	fd = open(fname, O_RDWR);
 
+	if (fd < 0) {
+		fd = WP_INVALID_SOCKET;
+	}
+
 	return fd;  
 #endif
 }            
@@ -106,11 +106,11 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
 
 	for(x = start; x < end; x++) {
 		zap_channel_t *chan;
-		zap_socket_t sockfd = -1;
+		zap_socket_t sockfd = WP_INVALID_SOCKET;
 		
 		sockfd = wp_open_device(spanno, x);
 		
-		if (sockfd > -1 && zap_span_add_channel(span, sockfd, type, &chan) == ZAP_SUCCESS) {
+		if (sockfd != WP_INVALID_SOCKET && 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 {
@@ -129,7 +129,6 @@ static unsigned wp_configure_channel(zap_config_t *cfg, const char *str, zap_spa
 	int channo;
 	int spanno;
 	int top = 0;
-	int x;
 	unsigned configured = 0;
 
 	assert(str != NULL);
@@ -380,6 +379,8 @@ static ZINT_WAIT_FUNCTION(wanpipe_wait)
 
 }
 
+#ifndef __WINDOWS__
+
 static ZINT_READ_FUNCTION(wanpipe_read_unix)
 {
 	int rx_len = 0;
@@ -416,17 +417,6 @@ static ZINT_READ_FUNCTION(wanpipe_read_unix)
 	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;
@@ -455,6 +445,19 @@ static ZINT_WRITE_FUNCTION(wanpipe_write_unix)
 
 }
 
+#endif
+
+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)
 {
 	ZINT_WRITE_MUZZLE;