[2/7] ws2_32: Convert send/recv flags to native system

Bruno Jesus 00cpxxx at gmail.com
Sat Mar 28 22:53:30 CDT 2015


Fortunately the only differences for now are listed below, my idea is
to find other options currently used by Windows applications and check
if we can support them someway in Wine. The unknown flags remain
untouched to match the current wine behavior.

I opted to convert the flags prior to calling WS2_recv and WS2_send
because when the socket is blocking they may be called hundreds of
times and converting everytime would be a waste. I also didn't want to
touch the wsa structure.

//FreeBSD
#define MSG_WAITALL   0x40

//Linux
#define MSG_WAITALL   0x100

//Windows
#define MSG_WAITALL   0x8
-------------- next part --------------

---
 dlls/ws2_32/socket.c | 59 ++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 48 insertions(+), 11 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 1bcb63c..cda9641 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -462,6 +462,14 @@ static void WS_AddCompletion( SOCKET sock, ULONG_PTR CompletionValue, NTSTATUS C
 
 #define MAP_OPTION(opt) { WS_##opt, opt }
 
+static const int ws_flags_map[][2] =
+{
+    MAP_OPTION( MSG_OOB ),
+    MAP_OPTION( MSG_PEEK ),
+    MAP_OPTION( MSG_DONTROUTE ),
+    MAP_OPTION( MSG_WAITALL ),
+};
+
 static const int ws_sock_map[][2] =
 {
     MAP_OPTION( SO_DEBUG ),
@@ -1014,6 +1022,33 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
 }
 
 /***********************************************************************
+ *          convert_flags()
+ *
+ * Converts send/recv flags from Windows format.
+ * Return the converted flag bits, unsupported flags remain unchanged.
+ */
+static int convert_flags(int flags)
+{
+    int i, out;
+    if (!flags) return 0;
+
+    for (out = i = 0; flags && i < sizeof(ws_flags_map) / sizeof(ws_flags_map[0]); i++)
+    {
+        if (ws_flags_map[i][0] & flags)
+        {
+            out |= ws_flags_map[i][1];
+            flags &= ~ws_flags_map[i][0];
+        }
+    }
+    if (flags)
+    {
+        FIXME("Unknown send/recv flags 0x%x, using anyway...\n", flags);
+        out |= flags;
+    }
+    return out;
+}
+
+/***********************************************************************
  *          convert_sockopt()
  *
  * Converts socket flags from Windows format.
@@ -1940,7 +1975,7 @@ static void WINAPI ws2_async_apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserv
  *
  * Workhorse for both synchronous and asynchronous recv() operations.
  */
-static int WS2_recv( int fd, struct ws2_async *wsa )
+static int WS2_recv( int fd, struct ws2_async *wsa, int flags )
 {
 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
     char pktbuf[512];
@@ -1970,7 +2005,7 @@ static int WS2_recv( int fd, struct ws2_async *wsa )
     hdr.msg_flags = 0;
 #endif
 
-    while ((n = recvmsg(fd, &hdr, wsa->flags)) == -1)
+    while ((n = recvmsg(fd, &hdr, flags)) == -1)
     {
         if (errno != EINTR)
             return -1;
@@ -2025,7 +2060,7 @@ static NTSTATUS WS2_async_recv( void *user, IO_STATUS_BLOCK *iosb,
         if ((status = wine_server_handle_to_fd( wsa->hSocket, FILE_READ_DATA, &fd, NULL ) ))
             break;
 
-        result = WS2_recv( fd, wsa );
+        result = WS2_recv( fd, wsa, convert_flags(wsa->flags) );
         wine_server_release_fd( wsa->hSocket, fd );
         if (result >= 0)
         {
@@ -2173,7 +2208,7 @@ finish:
  *
  * Workhorse for both synchronous and asynchronous send() operations.
  */
-static int WS2_send( int fd, struct ws2_async *wsa )
+static int WS2_send( int fd, struct ws2_async *wsa, int flags )
 {
     struct msghdr hdr;
     union generic_unix_sockaddr unix_addr;
@@ -2221,7 +2256,7 @@ static int WS2_send( int fd, struct ws2_async *wsa )
     hdr.msg_flags = 0;
 #endif
 
-    while ((ret = sendmsg(fd, &hdr, wsa->flags)) == -1)
+    while ((ret = sendmsg(fd, &hdr, flags)) == -1)
     {
         if (errno != EINTR)
             return -1;
@@ -2262,7 +2297,7 @@ static NTSTATUS WS2_async_send( void *user, IO_STATUS_BLOCK *iosb,
             break;
 
         /* check to see if the data is ready (non-blocking) */
-        result = WS2_send( fd, wsa );
+        result = WS2_send( fd, wsa, convert_flags(wsa->flags) );
         wine_server_release_fd( wsa->hSocket, fd );
 
         if (result >= 0)
@@ -4673,7 +4708,7 @@ static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
                        LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
 {
     unsigned int i, options;
-    int n, fd, err, overlapped;
+    int n, fd, err, overlapped, flags;
     struct ws2_async *wsa = NULL, localwsa;
     int totalLength = 0;
     DWORD bytes_sent;
@@ -4722,7 +4757,8 @@ static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
         totalLength += lpBuffers[i].len;
     }
 
-    n = WS2_send( fd, wsa );
+    flags = convert_flags(dwFlags);
+    n = WS2_send( fd, wsa, flags );
     if (n == -1 && errno != EAGAIN)
     {
         err = wsaErrno();
@@ -4814,7 +4850,7 @@ static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
                 goto error; /* msdn says a timeout in send is fatal */
             }
 
-            n = WS2_send( fd, wsa );
+            n = WS2_send( fd, wsa, flags );
             if (n == -1 && errno != EAGAIN)
             {
                 err = wsaErrno();
@@ -6712,7 +6748,7 @@ static int WS2_recv_base( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
                           LPWSABUF lpControlBuffer )
 {
     unsigned int i, options;
-    int n, fd, err, overlapped;
+    int n, fd, err, overlapped, flags;
     struct ws2_async *wsa = NULL, localwsa;
     BOOL is_blocking;
     DWORD timeout_start = GetTickCount();
@@ -6773,9 +6809,10 @@ static int WS2_recv_base( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
         wsa->iovec[i].iov_len  = lpBuffers[i].len;
     }
 
+    flags = convert_flags(wsa->flags);
     for (;;)
     {
-        n = WS2_recv( fd, wsa );
+        n = WS2_recv( fd, wsa, flags );
         if (n == -1)
         {
             if (errno != EAGAIN)
-- 
2.1.4



More information about the wine-patches mailing list