]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
implementations for the cross platform read and write in sangoma_tdm_api.h.
authorMichael Jerris <mike@jerris.com>
Sun, 20 May 2007 10:30:51 +0000 (10:30 +0000)
committerMichael Jerris <mike@jerris.com>
Sun, 20 May 2007 10:30:51 +0000 (10:30 +0000)
move zap_wanpipe.c to use the read and write from sangoma_tdm_api.h.
cleanups and lots of comments added to sangoma_tdm_api.h
some fixes to sangoma_tdm_api.h to make the api more consistent between windows and nix.

git-svn-id: http://svn.openzap.org/svn/openzap/trunk@51 a93c3328-9c30-0410-af19-c9cd2b2d52af

libs/freetdm/src/include/sangoma_tdm_api.h
libs/freetdm/src/zap_wanpipe.c

index 0d3f14da9613ed75ff0b237e6d87460029d122de..a795507c920ef9e70bbce2295edc4d1685c9f194 100644 (file)
@@ -1,9 +1,14 @@
 /*****************************************************************************
- * sangoma_tdm_api.h   Sangoma API Code Library
+ * sangoma_tdm_api.h   Sangoma TDM API Portability functions
  *
- * Author(s):  David Rokhvarg <davidr@sangoma.com>
+ * Author(s):  Anthony Minessale II <anthmct@yahoo.com>
+ *              Nenad Corbic <ncorbic@sangoma.com>
+ *                             Michael Jerris <mike@jerris.com>
+ *                             David Rokhvarg <davidr@sangoma.com>
  *
- * Copyright:  (c) 1984-2006 Sangoma Technologies Inc.
+ * Copyright:  (c) 2006 Nenad Corbic <ncorbic@sangoma.com>
+ *                       Anthony Minessale II
+ *                             (c) 1984-2007 Sangoma Technologies Inc.
  *
  * ============================================================================
  */
 #ifndef _SANGOMA_TDM_API_H
 #define _SANGOMA_TDM_API_H
 
+/* This entire block of defines and includes from this line, through #define FNAME_LEN probably dont belong here */
+/* most of them probably belong in wanpipe_defines.h, then each header file listed included below properly included */
+/* in the header files that depend on them, leaving only the include for wanpipe_tdm_api.h left in this file or */
+/* possibly integrating the rest of this file diretly into wanpipe_tdm_api.h */
 #ifndef __WINDOWS__
 #if defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)
 #define __WINDOWS__
-#endif
-#endif
+#endif /* defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32) */
+#endif /* ndef __WINDOWS__ */
 
-#ifdef __WINDOWS__
-#ifdef _MSC_VER
-/* 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:4200 4201 4214)
-#endif
+#if defined(__WINDOWS__)
+#if defined(_MSC_VER)
+/* disable some warnings caused by wanpipe headers that will need to be fixed in those headers */
+#pragma warning(disable:4201 4214)
+
+/* sang_api.h(74) : warning C4201: nonstandard extension used : nameless struct/union */
+
+/* wanpipe_defines.h(219) : warning C4214: nonstandard extension used : bit field types other than int */\r
+/* wanpipe_defines.h(220) : warning C4214: nonstandard extension used : bit field types other than int */
+/* this will break for any compilers that are strict ansi or strict c99 */
+
+/* The following definition for that struct should resolve this warning and work for 32 and 64 bit */
+#if 0
+struct iphdr {\r
+       \r
+#if defined(__LITTLE_ENDIAN_BITFIELD)\r
+       unsigned    ihl:4,\r
+                                                       version:4;\r
+#elif defined (__BIG_ENDIAN_BITFIELD)\r
+       unsigned    version:4,\r
+                                                       ihl:4;\r
+#else\r
+# error  "unknown byteorder!"\r
+#endif\r
+       unsigned    tos:8;\r
+       unsigned                tot_len:16;\r
+       unsigned                id:16;\r
+       unsigned                frag_off:16;\r
+       __u8    ttl;\r
+       __u8    protocol;\r
+       __u16   check;\r
+       __u32   saddr;\r
+       __u32   daddr;\r
+       /*The options start here. */\r
+};\r
+#endif /* #if 0 */
+
+#define __inline__ __inline
+#endif /* defined(_MSC_VER) */
 #include <windows.h>
+/* do we like the name WP_INVALID_SOCKET or should it be changed? */
 #define WP_INVALID_SOCKET INVALID_HANDLE_VALUE
-#else
+#else /* defined(__WINDOWS__) */ 
 #define WP_INVALID_SOCKET -1
 #include <stropts.h>
 #include <poll.h>
 
 #define FNAME_LEN      50
 
+/* what should the returns from this function be?? */
+/* I dont think they are currently consistant between windows and *nix */
 #ifdef __WINDOWS__
-static int tdmv_api_ioctl(sng_fd_t fd, wanpipe_tdm_api_cmd_t *tdm_api_cmd)
+static __inline__ int tdmv_api_ioctl(sng_fd_t fd, wanpipe_tdm_api_cmd_t *tdm_api_cmd)
 {
+       /* can we make the structure passed for this on nix and windows the same */
+       /* so we don't have to do the extra 2 memcpy's on windows for this ? */
        wan_udp_hdr_t   wan_udp;
        DWORD                   ln;
     unsigned char      id = 0;
-       int                             err = 0;
 
        wan_udp.wan_udphdr_request_reply = 0x01;
        wan_udp.wan_udphdr_id                    = id;
@@ -58,10 +104,7 @@ static int tdmv_api_ioctl(sng_fd_t fd, wanpipe_tdm_api_cmd_t *tdm_api_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));
+       memcpy( wan_udp.wan_udphdr_data, (void*)tdm_api_cmd, sizeof(wanpipe_tdm_api_cmd_t));
 
        if(DeviceIoControl(
                        fd,
@@ -73,44 +116,49 @@ static int tdmv_api_ioctl(sng_fd_t fd, wanpipe_tdm_api_cmd_t *tdm_api_cmd)
                        (LPDWORD)(&ln),
                        (LPOVERLAPPED)NULL
                        ) == FALSE){
-               //actual ioctl failed
-               err = 1;
-               return err;
-       }else{
-               err = 0;
+               return 1;
        }
 
        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));
+       memcpy( (void*)tdm_api_cmd, wan_udp.wan_udphdr_data, sizeof(wanpipe_tdm_api_cmd_t));
        return 0;
 }
 
 #else
-static int tdmv_api_ioctl(sng_fd_t fd, wanpipe_tdm_api_cmd_t *tdm_api_cmd)
+static __inline__ int tdmv_api_ioctl(sng_fd_t fd, wanpipe_tdm_api_cmd_t *tdm_api_cmd)
 {
        return ioctl(fd, SIOC_WANPIPE_TDM_API, tdm_api_cmd);
 }
 #endif
 
-static sng_fd_t tdmv_api_open_span_chan(int span, int chan) 
+void __inline__ tdmv_api_close_socket(sng_fd_t *sp) 
+{
+       if(     *sp != WP_INVALID_SOCKET){
+#if defined(__WINDOWS__)
+               CloseHandle(*sp);
+#else
+               close(*sp);
+#endif
+               *sp = WP_INVALID_SOCKET;
+       }
+}
+
+static __inline__ sng_fd_t tdmv_api_open_span_chan(int span, int chan) 
 {
        char fname[FNAME_LEN];
+       sng_fd_t fd = WP_INVALID_SOCKET;
 #if defined(__WINDOWS__)
+       DWORD                   ln;
+       wan_udp_hdr_t   wan_udp;
 
-       //NOTE: under Windows Interfaces are zero based but 'chan' is 1 based.
-       //              Subtract 1 from 'chan'.
+       /* NOTE: under Windows Interfaces are zero based but 'chan' is 1 based. */
+       /*              Subtract 1 from 'chan'. */
        _snprintf(fname , FNAME_LEN, "\\\\.\\WANPIPE%d_IF%d", span, chan - 1);
 
-       //prn(verbose, "Opening device: %s...\n", fname);
-
-       return CreateFile(      fname, 
+       fd = CreateFile(        fname, 
                                                GENERIC_READ | GENERIC_WRITE, 
                                                FILE_SHARE_READ | FILE_SHARE_WRITE,
                                                (LPSECURITY_ATTRIBUTES)NULL, 
@@ -118,9 +166,33 @@ static sng_fd_t tdmv_api_open_span_chan(int span, int chan)
                                                FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
                                                (HANDLE)NULL
                                                );
-#else
-       int fd = WP_INVALID_SOCKET;
 
+       /* make sure that we are the only ones who have this chan open */
+       /* is this a threadsafe way to make sure that we are ok and will */
+       /* never return a valid handle to more than one thread for the same channel? */
+
+       wan_udp.wan_udphdr_command = GET_OPEN_HANDLES_COUNTER; 
+       wan_udp.wan_udphdr_data_len = 0;
+
+       DeviceIoControl(
+               fd,
+               IoctlManagementCommand,
+               (LPVOID)&wan_udp,
+               sizeof(wan_udp_hdr_t),
+               (LPVOID)&wan_udp,
+               sizeof(wan_udp_hdr_t),
+               (LPDWORD)(&ln),
+               (LPOVERLAPPED)NULL
+               );
+
+       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);
+       }
+
+#else
+       /* Does this fail if another thread already has this chan open? */
+       /* if not, we need to add some code to make sure it does */
        snprintf(fname, FNAME_LEN, "/dev/wptdm_s%dc%d",span,chan);
 
        fd = open(fname, O_RDWR);
@@ -129,88 +201,23 @@ static sng_fd_t tdmv_api_open_span_chan(int span, int chan)
                fd = WP_INVALID_SOCKET;
        }
 
-       return fd;  
 #endif
+       return fd;  
 }            
 
-void tdmv_api_close_socket(sng_fd_t *sp) 
-{
-       if(     *sp != WP_INVALID_SOCKET){
 #if defined(__WINDOWS__)
-               CloseHandle(*sp);
-#else
-               close(*sp);
-#endif
-               *sp = WP_INVALID_SOCKET;
-       }
-}
-
-#ifdef __WINDOWS__
-
-// Blocking read command. If used after DoApiPollCommand(),
-// it will return immediatly, without blocking.
-static 
-USHORT 
-DoReadCommand(
-       sng_fd_t 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(
-       sng_fd_t 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;
-       }
-}
-
-#endif
-
-#if defined(__WINDOWS__)
-/* This is broken, we don't actually get real results for oob messages on windows */
+/* This might be broken on windows, as POLL_EVENT_TELEPHONY seems to be commented out in sang_api.h.. it should be added to POLLPRI */
 #define POLLPRI (POLL_EVENT_LINK_STATE | POLL_EVENT_LINK_CONNECT | POLL_EVENT_LINK_DISCONNECT)
 #endif
 
 /* return -1 for error, 0 for timeout, or POLLIN | POLLOUT | POLLPRI based on the result of the poll */
-int tdmv_api_wait_socket(sng_fd_t fd, int timeout, int flags)
+/* on windows we actually have POLLPRI defined with several events, so we could theoretically poll */
+/* for specific events.  Is there any way to do this on *nix as well? */ 
+
+/* 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)
 {
 #if defined(__WINDOWS__)
        DWORD ln;
@@ -279,4 +286,140 @@ int tdmv_api_wait_socket(sng_fd_t fd, int timeout, int flags)
 #endif
 }
 
+/* on windows right now, there is no way to specify if we want to read events here or not, we allways get them here */
+/* we need some what to select if we are reading regular tdm msgs or events */
+/* need to either have 2 functions, 1 for events, 1 for regural read, or a flag on this function to choose */
+/* 2 functions preferred.  Need implementation for the event function for both nix and windows that is threadsafe */
+static __inline__ int tdmv_api_readmsg_tdm(sng_fd_t fd, void *hdrbuf, int hdrlen, void *databuf, int datalen)\r
+{\r
+       /* What do we need to do here to avoid having to do all */\r
+       /* the memcpy's on windows and still maintain api compat with nix */\r
+       int rx_len=0;\r
+#if defined(__WINDOWS__)\r
+       static RX_DATA_STRUCT   rx_data;\r
+       api_header_t                    *pri;\r
+       wp_tdm_api_rx_hdr_t             *tdm_api_rx_hdr;\r
+       wp_tdm_api_rx_hdr_t             *user_buf = (wp_tdm_api_rx_hdr_t*)hdrbuf;\r
+       DWORD ln;
+\r
+       if(hdrlen != sizeof(wp_tdm_api_rx_hdr_t)){\r
+               return -1;\r
+       }\r
+\r
+       if(!DeviceIoControl(
+                       fd,
+                       IoctlReadCommand,
+                       (LPVOID)NULL,
+                       0L,
+                       (LPVOID)&rx_data,
+                       sizeof(RX_DATA_STRUCT),
+                       (LPDWORD)(&ln),
+                       (LPOVERLAPPED)NULL
+                       )){\r
+               return -1;\r
+       }\r
+\r
+       pri = &rx_data.api_header;\r
+       tdm_api_rx_hdr = (wp_tdm_api_rx_hdr_t*)rx_data.data;\r
+\r
+       user_buf->wp_tdm_api_event_type = pri->operation_status;\r
+\r
+       switch(pri->operation_status)\r
+       {\r
+       case SANG_STATUS_RX_DATA_AVAILABLE:\r
+               if(pri->data_length > datalen){\r
+                       break;\r
+               }\r
+               memcpy(databuf, rx_data.data, pri->data_length);\r
+               rx_len = pri->data_length;\r
+               break;\r
+\r
+       default:\r
+               break;\r
+       }\r
+\r
+#else\r
+       struct msghdr msg;\r
+       struct iovec iov[2];\r
+\r
+       memset(&msg,0,sizeof(struct msghdr));\r
+\r
+       iov[0].iov_len=hdrlen;\r
+       iov[0].iov_base=hdrbuf;\r
+\r
+       iov[1].iov_len=datalen;\r
+       iov[1].iov_base=databuf;\r
+\r
+       msg.msg_iovlen=2;\r
+       msg.msg_iov=iov;\r
+\r
+       rx_len = read(fd,&msg,datalen+hdrlen);\r
+\r
+       if (rx_len <= sizeof(wp_tdm_api_rx_hdr_t)){\r
+               return -EINVAL;\r
+       }\r
+\r
+       rx_len-=sizeof(wp_tdm_api_rx_hdr_t);\r
+#endif\r
+    return rx_len;\r
+}                    \r
+
+static __inline__ int tdmv_api_writemsg_tdm(sng_fd_t fd, void *hdrbuf, int hdrlen, void *databuf, unsigned short datalen)\r
+{\r
+       /* What do we need to do here to avoid having to do all */\r
+       /* the memcpy's on windows and still maintain api compat with nix */\r
+       int bsent = 0;\r
+#if defined(__WINDOWS__)\r
+       static TX_DATA_STRUCT   local_tx_data;\r
+       api_header_t                    *pri;\r
+       DWORD ln;\r
+\r
+       /* Are these really not needed or used???  What about for nix?? */\r
+       (void)hdrbuf;\r
+       (void)hdrlen;\r
+\r
+       pri = &local_tx_data.api_header;\r
+\r
+       pri->data_length = datalen;\r
+       memcpy(local_tx_data.data, databuf, pri->data_length);\r
+\r
+       if(!DeviceIoControl(\r
+                       fd,\r
+                       IoctlWriteCommand,\r
+                       (LPVOID)&local_tx_data,\r
+                       (ULONG)sizeof(TX_DATA_STRUCT),\r
+                       (LPVOID)&local_tx_data,\r
+                       sizeof(TX_DATA_STRUCT),\r
+                       (LPDWORD)(&ln),\r
+                       (LPOVERLAPPED)NULL\r
+                       )){\r
+               return -1;\r
+       }\r
+\r
+       if (local_tx_data.api_header.operation_status == SANG_STATUS_SUCCESS) {\r
+               bsent = datalen;\r
+       }\r
+#else\r
+       struct msghdr msg;\r
+       struct iovec iov[2];\r
+\r
+       memset(&msg,0,sizeof(struct msghdr));\r
+\r
+       iov[0].iov_len=hdrlen;\r
+       iov[0].iov_base=hdrbuf;\r
+\r
+       iov[1].iov_len=datalen;\r
+       iov[1].iov_base=databuf;\r
+\r
+       msg.msg_iovlen=2;\r
+       msg.msg_iov=iov;\r
+\r
+       bsent = write(fd,&msg,datalen+hdrlen);\r
+       if (bsent > 0){\r
+               bsent-=sizeof(wp_tdm_api_tx_hdr_t);\r
+       }\r
+#endif\r
+       return bsent;\r
+}\r
+
 #endif /* _SANGOMA_TDM_API_H */
index fc7142dc4860732793bc4fab999870945acce7ef..013da15be51423bf1c0c0561ed045ebeb73dca0f 100644 (file)
@@ -311,135 +311,15 @@ static ZINT_COMMAND_FUNCTION(wanpipe_command)
        return ZAP_SUCCESS;
 }
 
-#ifdef __WINDOWS__
-
-static ZINT_READ_FUNCTION(wanpipe_read_windows)
-{
-       zap_size_t rx_len = 0;
-       zap_status_t status = ZAP_FAIL;
-
-       /* should we just pass in abuffer big enough in the first place instead of having to use rx_data and memcpy here? */
-       static RX_DATA_STRUCT   rx_data;
-
-       if(DoReadCommand(zchan->sockfd, &rx_data)) {
-               snprintf(zchan->last_error, sizeof(zchan->last_error), "Error: DoReadCommand() failed! Check messages log.\n");
-               goto done;
-       }
-
-       switch(rx_data.api_header.operation_status)
-       {
-       case SANG_STATUS_RX_DATA_AVAILABLE:
-               if(rx_data.api_header.data_length > *datalen){
-                       snprintf(zchan->last_error, sizeof(zchan->last_error), "Buffer overrun.\n");
-                       break;
-               }
-               memcpy(data, rx_data.data, rx_data.api_header.data_length);
-               rx_len = rx_data.api_header.data_length;
-               status = ZAP_SUCCESS;
-               break;
-
-       case SANG_STATUS_TDM_EVENT_AVAILABLE:
-               memcpy(data, rx_data.data, rx_data.api_header.data_length);
-               rx_len = rx_data.api_header.data_length;
-               status = ZAP_SUCCESS;
-               break;
-
-       case SANG_STATUS_RX_DATA_TIMEOUT:
-               snprintf(zchan->last_error, sizeof(zchan->last_error), "Error: Timeout on read.\n");
-               break;
-
-       case SANG_STATUS_BUFFER_TOO_SMALL:
-               snprintf(zchan->last_error, sizeof(zchan->last_error), "Error: Received data longer than buffer passed to API.\n");
-               break;
-
-       case SANG_STATUS_LINE_DISCONNECTED:
-               snprintf(zchan->last_error, sizeof(zchan->last_error), "Error: Line disconnected.\n");
-               break;
-
-       default:
-               snprintf(zchan->last_error, sizeof(zchan->last_error), "Rx:Unknown Operation Status: %d\n", rx_data.api_header.operation_status);
-               break;
-       }
-
-done:
-       *datalen = rx_len;
-       return status;
-}
-
-static ZINT_WRITE_FUNCTION(wanpipe_write_windows)
-{
-       static TX_DATA_STRUCT   local_tx_data;
-
-       /* why don't we just provide the big enough buffer to start with so we can avoid the memcpy ? */
-       memcpy(local_tx_data.data, data, *datalen);
-
-       /* queue data for transmission */
-       if(DoWriteCommand(zchan->sockfd, &local_tx_data)) {
-               snprintf(zchan->last_error, sizeof(zchan->last_error), "Error: DoWriteCommand() failed!! Check messages log.\n");
-               *datalen = 0;
-               return ZAP_FAIL;
-       }
-
-       if (local_tx_data.api_header.operation_status == SANG_STATUS_SUCCESS) {
-               return ZAP_SUCCESS;
-       }
-
-       *datalen = 0;
-
-       switch(local_tx_data.api_header.operation_status)
-       {
-       case SANG_STATUS_TX_TIMEOUT:
-               snprintf(zchan->last_error, sizeof(zchan->last_error), "****** Error: SANG_STATUS_TX_TIMEOUT ******\n");
-               break;
-                               
-       case SANG_STATUS_TX_DATA_TOO_LONG:
-               snprintf(zchan->last_error, sizeof(zchan->last_error), "****** SANG_STATUS_TX_DATA_TOO_LONG ******\n");
-               break;
-                               
-       case SANG_STATUS_TX_DATA_TOO_SHORT:
-               snprintf(zchan->last_error, sizeof(zchan->last_error),  "****** SANG_STATUS_TX_DATA_TOO_SHORT ******\n");
-               break;
-
-       case SANG_STATUS_LINE_DISCONNECTED:
-               snprintf(zchan->last_error, sizeof(zchan->last_error),  "****** SANG_STATUS_LINE_DISCONNECTED ******\n");
-               break;
-
-       default:
-               snprintf(zchan->last_error, sizeof(zchan->last_error),  "Unknown return code (0x%X) on transmission!\n", local_tx_data.api_header.operation_status);
-               break;
-       }
-
-       return ZAP_FAIL;
-}
-
-#else
-
-static ZINT_READ_FUNCTION(wanpipe_read_unix)
+static ZINT_READ_FUNCTION(wanpipe_read)
 {
        int rx_len = 0;
-       struct msghdr msg;
-       struct iovec iov[2];
        wp_tdm_api_rx_hdr_t hdrframe;
 
-       memset(&msg, 0, sizeof(msg));
        memset(&hdrframe, 0, sizeof(hdrframe));
-       memset(iov, 0, sizeof(iov[0])*2);
-
-       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 + iov[0].iov_len);
+       rx_len = tdmv_api_readmsg_tdm(zchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (int)*datalen);
        
-       if (rx_len > 0) {
-               rx_len -= sizeof(hdrframe);
-       }
-
        *datalen = rx_len;
 
        if (rx_len <= 0) {
@@ -450,37 +330,24 @@ static ZINT_READ_FUNCTION(wanpipe_read_unix)
        return ZAP_SUCCESS;
 }
 
-static ZINT_WRITE_FUNCTION(wanpipe_write_unix)
+static ZINT_WRITE_FUNCTION(wanpipe_write)
 {
        int bsent;
-       struct msghdr msg;
-       struct iovec iov[2];
        wp_tdm_api_tx_hdr_t hdrframe;
 
-       memset(&msg, 0, sizeof(msg));
+       /* Do we even need the headerframe here? on windows, we don't even pass it to the driver */
        memset(&hdrframe, 0, sizeof(hdrframe));
-       memset(iov, 0, sizeof(iov[0])*2);
-       
-       iov[0].iov_len = sizeof(hdrframe);
-       iov[0].iov_base = &hdrframe;
+       bsent = tdmv_api_writemsg_tdm(zchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (unsigned short)(*datalen));
 
-       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 + iov[0].iov_len);
-
-       if (bsent > 0){
-               bsent -= sizeof(wp_tdm_api_tx_hdr_t);
+       /* should we be checking if bsent == *datalen here? */
+       if (bsent > 0) {
+               *datalen = bsent;
+               return ZAP_SUCCESS;
        }
 
-       *datalen = bsent;
-
-       return ZAP_SUCCESS;
+       return ZAP_FAIL;
 }
 
-#endif
 
 static ZINT_WAIT_FUNCTION(wanpipe_wait)
 {
@@ -527,13 +394,8 @@ zap_status_t wanpipe_init(zap_software_interface_t **zint)
        wanpipe_interface.close = wanpipe_close;
        wanpipe_interface.command = wanpipe_command;
        wanpipe_interface.wait = wanpipe_wait;
-#ifdef __WINDOWS__
-       wanpipe_interface.read = wanpipe_read_windows;
-       wanpipe_interface.write = wanpipe_write_windows;
-#else
-       wanpipe_interface.read = wanpipe_read_unix;
-       wanpipe_interface.write = wanpipe_write_unix;
-#endif
+       wanpipe_interface.read = wanpipe_read;
+       wanpipe_interface.write = wanpipe_write;
        *zint = &wanpipe_interface;
 
        return ZAP_SUCCESS;