mswsock.dll: TranmitFile - new way [1/2]

Łukasz Chróst lukost at gmail.com
Tue Jun 27 18:17:57 CDT 2006


Changelog:
- added non-overlapped TransmitFile based totally on ws2_32 functions
(compiles for windows also).
- all used functions are user-level

Bugs:
- the functions is non-overlapped and blocking only for now

--
Lukasz Chrost

-------------- next part --------------
Index: dlls/mswsock/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/mswsock/Makefile.in,v
retrieving revision 1.3
diff -u -r1.3 Makefile.in
--- dlls/mswsock/Makefile.in	9 May 2005 14:42:33 -0000	1.3
+++ dlls/mswsock/Makefile.in	27 Jun 2006 23:13:09 -0000
@@ -4,13 +4,16 @@
 VPATH     = @srcdir@
 MODULE    = mswsock.dll
 IMPORTLIB = libmswsock.$(IMPLIBEXT)
-IMPORTS   = ws2_32 iphlpapi kernel32
+IMPORTS   = ws2_32 kernel32 
+
 
 C_SRCS = \
 	mswsock.c
 
 RC_SRCS = version.rc
 
+SUBDIRS = tests
+
 @MAKE_DLL_RULES@
 
 ### Dependencies:
Index: dlls/mswsock/mswsock.c
===================================================================
RCS file: /home/wine/wine/dlls/mswsock/mswsock.c,v
retrieving revision 1.4
diff -u -r1.4 mswsock.c
--- dlls/mswsock/mswsock.c	23 May 2006 12:48:20 -0000	1.4
+++ dlls/mswsock/mswsock.c	27 Jun 2006 22:56:18 -0000
@@ -29,6 +29,15 @@
 
 #include "wine/debug.h"
 
+/* ************************************************************************************************ */
+/* Handle validation against INVALID_HANDLE_VALUE */
+#define HANDLE_VALID(x) (!(x==INVALID_HANDLE_VALUE))
+
+/* maximum system-defined data junk we try to post via single read-file-write-socket operation */
+#define FILE_DATA_BUFFER_LENGTH 2048
+
+
+/* ************************************************************************************************ */
 WINE_DEFAULT_DEBUG_CHANNEL(mswsock);
 
 /***********************************************************************
@@ -89,33 +98,190 @@
 {
     FIXME("not implemented\n");
 }
+/***********************************************************************
+ * SendDataBuffer (INTERNAL) 
+ * send data buffer not longer than maximum allowed, blocks even non-blocking IO */
+ 
+
+static DWORD SendDataBufferBlock(SOCKET hSocket, LPVOID buf, DWORD buflen,
+    DWORD junksize, DWORD maxwrite)
+{
+    DWORD dwBytesSent   = 0;
+    DWORD dwRetVal      = 0;
+    DWORD dwBytesLeft   = (buflen < maxwrite) ? buflen: maxwrite;
+    fd_set writeset;
+    
+    FD_ZERO(&writeset);
+    FD_SET (hSocket, &writeset);
+    
+    while(dwBytesLeft)
+    {
+        if((dwRetVal = select(0, 0, &writeset, 0, 0)) == SOCKET_ERROR)
+            goto e_exit;
 
+        dwRetVal = send(hSocket, &((char *)buf)[dwBytesSent],
+            (dwBytesLeft < junksize) ? dwBytesLeft : junksize,0);
+
+        if(dwRetVal == SOCKET_ERROR)
+            goto e_exit;
+        
+        dwBytesLeft -= dwRetVal;
+        dwBytesSent += dwRetVal;
+    }    
+    FD_ZERO(&writeset);
+    return dwBytesSent ;
+
+e_exit:    
+    FD_ZERO(&writeset);
+    return SOCKET_ERROR;
+}
+ 
+ 
 /***********************************************************************
- *		TransmitFile (MSWSOCK.@)
+ *              WSAAddressToStringW                      (MSWSOCK.@)
  *
- * This function is used to transmit a file over socket.
+ * Transmit file via socket. Header  / Footer data is also supported.
  *
- * TODO
- *  This function is currently implemented as a stub.
+ * PARAMS
+ *  hSocket [I]    Socket for sending the data. Not handle.
+ *  hFile      [I]    file to transmit.
+ *  nNumberOfBytesToWrite     [I]    How much data to write. Optional 
+ *  nNumberOfBytesPerSend  [I] Maximum length of single packet (usefull for communication protocols)
+ *  lpOverlapped [I/O] used for overlapped operations 
+ *  lpTransmitBuffers [I] data to send as header/tail usefull for communication protocols)
+ * dwFlags [I] communication flags. 
+ *
+ * RETURNS
+ *  Success: non-overlapped: TRUE, overlapped: TRUE/FALSE (check real result with WSAGetOverlappedResult)
+ *  Failure: FALSE
+ *
+ * NOTES
+ *  Use lpOverlapped->Offset for file offset
+ *
+ * BUGS
+ *  lpOverlapped->OffsetHigh  is not supported.
+ *  limited to ULONG long files size (see above)
+ *  doesn't support TF_REUSE_SOCKET and TF_REUSE_SOCKET
+ *  doesn't support async IO
  */
 
-BOOL WINAPI TransmitFile(
-        SOCKET hSocket, /* [in] Handle to a connected socket */
-	HANDLE hFile,   /* [in] Handle to the open file that should be
-                           transmited */
-	DWORD nNumberOfBytesToWrite, /* [in] Number of file bytes to 
-                                        transmit */
-	DWORD nNumberOfBytesPerSend, /* [in] Size in bytes of each block of
-                                         data sent in each send operation */
-	LPOVERLAPPED lpOverlapped, /* [in] Specify in order to achieve an 
-                                      overlapped (asynchronous) I/O 
-                                      operation */
-	LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, 
-		/* [in] Contains pointers to data to send before and after
-                   the file data is sent */
-	DWORD dwFlags) /* [in] Flags */
+BOOL WINAPI TransmitFile(SOCKET hSocket, HANDLE hFile, DWORD nNumberOfBytesToWrite,
+  	DWORD nNumberOfBytesPerSend, LPOVERLAPPED lpOverlapped, 
+    LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, 	DWORD dwFlags)
 {
-    FIXME("not implemented\n");
+    DWORD dwBytesSent   = 0, dwTotalBytesSent = 0;
+    DWORD dwReadLen     = 0;    
+    DWORD dwRetVal      = 0;
+    LPVOID lpstrBuffer   = 0;
+        
+    TRACE("hSocket %04x, hFile %p, nbytes %ld, npsize %ld,  ovl %p, tfbuf %p, flags %ld\n",
+            hSocket, hFile, nNumberOfBytesToWrite, nNumberOfBytesPerSend, 
+            lpOverlapped, lpTransmitBuffers, dwFlags);    
+    
+    if(!HANDLE_VALID(hFile))
+    {
+        WSASetLastError(WSAEINVAL);
+        return FALSE;
+    }
+    
+    if(dwFlags & TF_REUSE_SOCKET) 
+        FIXME("TF_REUSE_SOCKET has no effect.\n");
+        
+   
+    if(lpOverlapped)
+    {
+        FIXME("WARNING: Overlapped operation is not supported.\n");
+        if(lpOverlapped->Offset || lpOverlapped->OffsetHigh)
+        {
+            dwRetVal = SetFilePointer( hFile, lpOverlapped->Offset, 
+                &lpOverlapped->OffsetHigh, FILE_BEGIN);
+            if(dwRetVal == INVALID_SET_FILE_POINTER)
+            {
+                if(GetLastError() != NO_ERROR)
+                {
+                    WSASetLastError(WSAEINVAL);
+                    return FALSE;
+                }
+            }
+        }
+    }
+        
+    if(nNumberOfBytesPerSend > FILE_DATA_BUFFER_LENGTH) /*we are using local var anyway */
+        nNumberOfBytesPerSend = FILE_DATA_BUFFER_LENGTH; 
+    if(!nNumberOfBytesPerSend)
+        nNumberOfBytesPerSend = FILE_DATA_BUFFER_LENGTH; 
+    if(!nNumberOfBytesToWrite)
+        nNumberOfBytesToWrite = -1; /* should be OK */
+    
+    dwRetVal = SendDataBufferBlock(hSocket, lpTransmitBuffers->Head, 
+        lpTransmitBuffers->HeadLength, nNumberOfBytesPerSend, nNumberOfBytesToWrite);
+    if(dwRetVal == SOCKET_ERROR)
+        goto e_exit;
+        
+    dwTotalBytesSent += dwBytesSent;
+    if(!(nNumberOfBytesToWrite -= dwBytesSent))
+        goto ok_exit;
+
+    if(hFile)
+    {
+        lpstrBuffer = HeapAlloc( GetProcessHeap(), 0, FILE_DATA_BUFFER_LENGTH);
+        if(!lpstrBuffer)
+        {
+            WSASetLastError(WSAENOBUFS);
+            goto e_exit;
+        }
+        
+        while(nNumberOfBytesToWrite)
+        {
+            dwRetVal = ReadFile(hFile, lpstrBuffer, 
+                (nNumberOfBytesToWrite < nNumberOfBytesPerSend) ?
+                    nNumberOfBytesToWrite : nNumberOfBytesPerSend,
+                &dwReadLen, 0);
+
+            if(!dwRetVal)
+            {
+                WSASetLastError(WSAEACCES);
+                goto e_exit;
+            }
+            
+            if(!dwReadLen) /* we are beyond EOF */
+                break;
+                
+            dwRetVal = SendDataBufferBlock(hSocket, lpstrBuffer, dwReadLen,
+                nNumberOfBytesPerSend, nNumberOfBytesToWrite);
+            
+            if(dwRetVal == SOCKET_ERROR)
+                goto e_exit;       
+
+            dwTotalBytesSent += dwBytesSent;
+            if(!(nNumberOfBytesToWrite -= dwBytesSent))
+                goto ok_exit;
+        }
+    }
+
+    dwRetVal = SendDataBufferBlock(hSocket, lpTransmitBuffers->Tail, 
+        lpTransmitBuffers->TailLength, nNumberOfBytesPerSend, nNumberOfBytesToWrite);
+    if(dwRetVal == SOCKET_ERROR)
+        goto e_exit;
+    
+    dwTotalBytesSent += dwBytesSent;
+    if(dwFlags & TF_DISCONNECT) 
+    
+
+ok_exit:
+    if(lpOverlapped)
+        lpOverlapped->Internal = dwTotalBytesSent; /* FIXME */
+    if(lpstrBuffer)
+        HeapFree( GetProcessHeap(), 0, lpstrBuffer);    
+        
+    if(dwFlags & TF_DISCONNECT) 
+        closesocket(hSocket);
+        
+    return TRUE;
+            
+e_exit:
+    if(lpstrBuffer)
+        HeapFree( GetProcessHeap(), 0, lpstrBuffer);    
 
     return FALSE;
 }


More information about the wine-patches mailing list