[mswsock] TransmitFile should work now [2/4] - source

Łukasz Chróst lukost at gmail.com
Thu Jun 29 08:56:00 CDT 2006


changelog:
    - created new TransmitFile (non-overlapped).
    - use only ws2_32 functions for socket handling
    - function performs some basic async simulation (it should not block
when WSAGetOverlappedResult is called on error)

--
Łukasz Chróst
-------------- next part --------------
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	29 Jun 2006 13:11:15 -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);
 
 /***********************************************************************
@@ -91,6 +100,42 @@
 }
 
 /***********************************************************************
+ * SendDataBuffer (INTERNAL) 
+ * send data buffer not longer than maximum allowed, notes: blocks even non-blocking socket operations */
+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.@)
  *
  * This function is used to transmit a file over socket.
@@ -115,8 +160,128 @@
                    the file data is sent */
 	DWORD dwFlags) /* [in] Flags */
 {
-    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);
+        goto e_exit;
+    }
+    
+    if(dwFlags & TF_REUSE_SOCKET) 
+        FIXME("TF_REUSE_SOCKET has no effect.\n");
+        
+    if(lpOverlapped)
+    {
+        FIXME("WARNING: Overlapped operation is not supported.\n");
+        /* this is an overlapped io simulation variable - how much data has been actualy sent*/
+        lpOverlapped->Internal = 0;
+        if(hFile)
+        {
+            dwRetVal = SetFilePointer( hFile, lpOverlapped->Offset, 
+                &lpOverlapped->OffsetHigh, FILE_BEGIN);
+            if(dwRetVal == INVALID_SET_FILE_POINTER)
+            {
+                if(GetLastError() != NO_ERROR)
+                {
+                    WSASetLastError(WSAEINVAL);
+                    return FALSE;
+                }
+            }
+        }
+    }
+    /* check for actual data junk size for sending / reading file data */
+    if(nNumberOfBytesPerSend > FILE_DATA_BUFFER_LENGTH) 
+        nNumberOfBytesPerSend = FILE_DATA_BUFFER_LENGTH; 
+    if(!nNumberOfBytesPerSend)
+        nNumberOfBytesPerSend = FILE_DATA_BUFFER_LENGTH; 
+        
+    /* this could lead into problems if the actual amount of data to send exceeds ULONG. */
+    if(!nNumberOfBytesToWrite)
+        nNumberOfBytesToWrite = -1; 
+    
+    /* send header */
+    dwRetVal = SendDataBufferBlock(hSocket, lpTransmitBuffers->Head, 
+        lpTransmitBuffers->HeadLength, nNumberOfBytesPerSend, nNumberOfBytesToWrite);
+    if(dwRetVal == SOCKET_ERROR)
+        goto e_exit;
+        
+    dwTotalBytesSent += dwBytesSent;
+    if(!(nNumberOfBytesToWrite -= dwBytesSent))
+        goto ok_exit;
+
+    /* send file */
+    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)
+                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;
+
+    ok_exit:
+    /*we are simulating overlapped operation below, but we want async to be implemented separately, that needs to be fixed */
+    if(lpOverlapped)
+        lpOverlapped->Internal = dwTotalBytesSent; /* FIXME */
+    if(lpOverlapped)
+        SetEvent(lpOverlapped->hEvent);            /* FIXME */        
+
+    if(lpstrBuffer)
+        HeapFree( GetProcessHeap(), 0, lpstrBuffer);    
+  
+    if(dwFlags & TF_DISCONNECT) 
+        closesocket(hSocket);
+    
+    WSASetLastError(NO_ERROR);
+        
+    return TRUE;
+            
+e_exit:
+    if(lpstrBuffer)
+        HeapFree( GetProcessHeap(), 0, lpstrBuffer);    
+    /*we are simulating overlapped operation below, but we want async to be implemented separately */                        
+    if(lpOverlapped)
+        SetEvent(lpOverlapped->hEvent);             /* FIXME */        
     return FALSE;
 }
 
@@ -131,6 +296,6 @@
 	               fully or partially received for datagram sockets */
 {
     FIXME("not implemented\n");
-    
+  
     return SOCKET_ERROR;
 }


More information about the wine-patches mailing list