[PATCH] Move recv() functionality to WS2_32 code

Martin Wilck Martin.Wilck at fujitsu-siemens.com
Thu Apr 4 06:44:48 CST 2002


PATCH: Move recv() functionality to WS2_32 code

For the recv() family of functions, WSARecvFrom() becomes the work horse.
All other functions (WSARecv(), recv(), recvfrom(), ...) are only wrappers
around WSARecvFrom().

To provide the scatter/gather functionality of WSARecvFrom(), the Unix system call
used as backend is recvmsg() rather than recvfrom().

Patch against:  Wine CVS 2002-04-04.

Test status:    Compiles, no warnings.
                Tested with 16 bit apps: FreeAgent (newsreader), Solstice mail,
                        nslookup, teraterm (telnet)
                (16 bit apps now call WS2_32 code!)

Modified files:
        dlls/winsock    : socket.c, ws2_32.spec

diff -ruNX diffignore MW/wine/dlls/winsock/socket.c TMP/wine/dlls/winsock/socket.c
--- MW/wine/dlls/winsock/socket.c	Thu Apr  4 09:37:38 2002
+++ TMP/wine/dlls/winsock/socket.c	Thu Apr  4 10:58:53 2002
@@ -1797,34 +1797,13 @@
  */
 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
 {
-    int fd = _get_sock_fd(s);
-
-    TRACE("socket %04x, buf %8x, len %d, flags %d\n", s, (unsigned)buf, len, flags);
-
-    if (fd != -1)
-    {
-	INT length;
-
-	if (_is_blocking(s))
-	{
-	    /* block here */
-	    /* FIXME: OOB and exceptfds? */
-	    do_block(fd, 1);
-	}
-	if ((length = recv(fd, buf, len, flags)) >= 0)
-	{
-	    TRACE(" -> %i bytes\n", length);
+    DWORD n, dwFlags = flags;
+    WSABUF wsabuf = { len, buf };

-	    close(fd);
-	    _enable_event(s, FD_READ, 0, 0);
-	    return length;
-	}
-	SetLastError(wsaErrno());
-	close(fd);
-    }
-    else SetLastError(WSAENOTSOCK);
-    WARN(" -> ERROR\n");
-    return SOCKET_ERROR;
+    if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
+        return SOCKET_ERROR;
+    else
+        return n;
 }

 /***********************************************************************
@@ -1842,60 +1821,13 @@
 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
                                 struct WS_sockaddr *from, int *fromlen)
 {
-    int fd = _get_sock_fd(s);
-    int res;
+    DWORD n, dwFlags = flags;
+    WSABUF wsabuf = { len, buf };

-    TRACE("socket %04x, ptr %08x, len %d, flags %d\n", s, (unsigned)buf, len, flags);
-#if DEBUG_SOCKADDR
-    if (from)
-        dump_sockaddr(from);
+    if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
+        return SOCKET_ERROR;
     else
-        DPRINTF("from = NULL\n");
-#endif
-
-    res=SOCKET_ERROR;
-    if (fd != -1)
-    {
-        struct sockaddr* uaddr;
-        int uaddrlen;
-        int length;
-
-        if (_is_blocking(s))
-        {
-            /* block here */
-            /* FIXME: OOB and exceptfds */
-            do_block(fd, 1);
-        }
-
-        uaddr=ws_sockaddr_alloc(from,fromlen,&uaddrlen);
-        length=recvfrom(fd, buf, len, flags, uaddr, &uaddrlen);
-        if (length < 0)
-        {
-            SetLastError(wsaErrno());
-            WARN(" -> ERROR\n");
-        }
-        else if (ws_sockaddr_u2ws(uaddr,uaddrlen,from,fromlen) != 0)
-        {
-            /* The from buffer was too small, but we read the data
-             * anyway. Is that really bad?
-             */
-            SetLastError(WSAEFAULT);
-            WARN(" -> WSAEFAULT\n");
-        }
-        else
-        {
-            TRACE(" -> %i bytes\n", length);
-            _enable_event(s, FD_READ, 0, 0);
-            res=length;
-        }
-        close(fd);
-    }
-    else
-    {
-        SetLastError(WSAENOTSOCK);
-        WARN(" -> WSAENOTSOCK\n");
-    }
-    return res;
+        return n;
 }

 /***********************************************************************
@@ -3302,34 +3234,129 @@


 /***********************************************************************
+ *		WSARecv			(WS2_32.67)
+ */
+int WINAPI WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
+		    LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
+		    LPWSAOVERLAPPED lpOverlapped,
+		    LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+{
+    return WSARecvFrom (s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
+                        NULL, NULL, lpOverlapped, lpCompletionRoutine);
+}
+
+/***********************************************************************
  *              WSARecvFrom             (WS2_32.69)
  */
 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
                         LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
                         LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
                         LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
+
 {
-  DWORD dwCount;
-  INT   rc;
+    /* Uses recvmsg() in order to provide scatter-gather I/O */
+
+    struct iovec* iovec;
+    struct msghdr msghdr;
+    int fd, i, length, err = WSAENOTSOCK;
+
+    TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
+          s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
+          (lpFromlen ? *lpFromlen : -1L),
+          lpOverlapped, lpCompletionRoutine);
+
+    fd = _get_sock_fd(s);

-  FIXME( "(%i,%p,%lu,%p,%p,%p,%p,%p,%p: stub\n",
-         s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags,
-         lpFrom, lpFromlen, lpOverlapped, lpCompletionRoutine );
+    if (fd == -1)
+    {
+        err = WSAENOTSOCK;
+        goto error;
+    }

-  for( dwCount = 0, rc = 0; dwCount < dwBufferCount; dwCount++ )
-  {
+    /* FIXME: should this be HeapAlloc() or WS_ALLOC ? */
+    iovec = WS_ALLOC ( dwBufferCount * sizeof (struct iovec) );
+    if ( !iovec )
+    {
+        err = WSAENOBUFS;
+        goto err_close;
+    }

-    if( ( rc = WS_recvfrom(s, lpBuffers[ dwCount ].buf, (INT)lpBuffers[ dwCount ].len,
-                                (INT)*lpFlags, lpFrom, lpFromlen ) ) != 0 )
+    for (i = 0; i < dwBufferCount; i++)
     {
-       break;
+        iovec[i].iov_base = lpBuffers[i].buf;
+        iovec[i].iov_len  = lpBuffers[i].len;
     }

-  }
+    msghdr.msg_name = NULL;

-  return rc;
-}
+    if ( lpFrom )
+    {
+#if DEBUG_SOCKADDR
+        dump_sockaddr (lpFrom);
+#endif
+
+        msghdr.msg_namelen = *lpFromlen;
+        msghdr.msg_name = ws_sockaddr_alloc (lpFrom, lpFromlen, &msghdr.msg_namelen);
+    }
+    else
+        msghdr.msg_namelen = 0;
+
+    msghdr.msg_iov = iovec;
+    msghdr.msg_iovlen = dwBufferCount;
+    msghdr.msg_control = NULL;
+    msghdr.msg_controllen = 0;
+    msghdr.msg_flags = 0;
+
+    /* FIXME: Treat overlapped IO here */
+
+    if (_is_blocking(s))
+    {
+        /* block here */
+        /* FIXME: OOB and exceptfds? */
+        do_block(fd, 1);
+    }
+
+    /* FIXME: can we support MSG_PARTIAL ?
+       How does it relate to recvmsg()'s msg_flags ? */
+
+    if ((length = recvmsg (fd, &msghdr, *lpFlags)) == -1)
+    {
+        err = wsaErrno();
+        goto err_free;
+    }
+
+    TRACE(" -> %i bytes\n", length);
+
+    if ( lpFrom && ws_sockaddr_u2ws (msghdr.msg_name, msghdr.msg_namelen, lpFrom, lpFromlen) != 0 )
+    {
+        /* The from buffer was too small, but we read the data
+         * anyway. Is that really bad?
+         */
+        SetLastError ( WSAEFAULT );
+        WARN ( " -> Address buffer too small\n" );
+    }
+
+    *lpNumberOfBytesRecvd = length;

+    WS_FREE (iovec);
+    ws_sockaddr_free ( msghdr.msg_name, lpFrom );
+    close(fd);
+    _enable_event(s, FD_READ, 0, 0);
+
+    return 0;
+
+err_free:
+    WS_FREE (iovec);
+    ws_sockaddr_free ( msghdr.msg_name, lpFrom );
+
+err_close:
+    close (fd);
+
+error:
+    WARN(" -> ERROR %d\n", err);
+    SetLastError ( err );
+    return SOCKET_ERROR;
+}

 /***********************************************************************
  *              WSCInstallProvider             (WS2_32.88)
diff -ruNX diffignore MW/wine/dlls/winsock/ws2_32.spec TMP/wine/dlls/winsock/ws2_32.spec
--- MW/wine/dlls/winsock/ws2_32.spec	Thu Apr  4 09:37:38 2002
+++ TMP/wine/dlls/winsock/ws2_32.spec	Thu Apr  4 10:58:53 2002
@@ -79,7 +79,7 @@
 64  stub     WSANtohl
 65  stub     WSANtohs
 66  stub     WSAProviderConfigChange
-67  stub     WSARecv
+67  stdcall  WSARecv(long ptr long ptr ptr ptr ptr) WSARecv
 68  stub     WSARecvDisconnect
 69  stdcall  WSARecvFrom(long ptr long ptr ptr ptr ptr ptr ptr ) WSARecvFrom
 70  stub     WSARemoveServiceClass






More information about the wine-patches mailing list