[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