Patch: 005-recv.diff

Martin Wilck Martin.Wilck at fujitsu-siemens.com
Mon Jan 7 09:38:10 CST 2002


#5 in series

Patch file:	005-recv.diff
Purpose:	Move recv() functionality to WS2_32 code
Created:	2002-01-07
Applies:	CVS 2002-01-07
		(with 004-socket.diff applied)

This patch moves the recv() functionality to WS2_32 functions
that provide a superset of the functionality of their WS counterparts.

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 WSARecv() / WSARecvFrom(),
the (only) unix function called is recvmsg(). This means some overhead for
simple recv() calls, but allows for a single general "work" code.

dlls/winsock/socket.c:
	WS_recv():	Is now a wrapper around WSARecv().
	WS_recvfrom():	Is now a wrapper around WSARecvFrom().
	WSARecv():	Is now a wrapper around WSARecvFrom().
	WSARecvFrom():	Holds all "real" recv() functionality
		(formerly in WS_recv() / WS_recvfrom()).
		Calls recvmsg() to provide for scatter/gather functionality.
dlls/winsock/ws2_32.spec:
	Add stdcall entry for WSARecv().

Martin Wilck <Martin.Wilck at Fujitsu-Siemens.com>

diff -ru -X diffignore CVS/wine/dlls/winsock/socket.c MW/wine/dlls/winsock/socket.c
--- CVS/wine/dlls/winsock/socket.c	Mon Jan  7 12:55:24 2002
+++ MW/wine/dlls/winsock/socket.c	Mon Jan  7 12:55:37 2002
@@ -1815,34 +1815,16 @@
  */
 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
 {
-    int fd = _get_sock_fd(s);
+    DWORD n;
+    WSABUF wsabuf = { len, buf };
+    DWORD dwFlags = flags;

     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);
-
-	    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 ( WSARecv (s, &wsabuf, 1, &n, &dwFlags, NULL, NULL) == SOCKET_ERROR )
+        return SOCKET_ERROR;
+    else
+        return n;
 }

 /***********************************************************************
@@ -1860,60 +1842,14 @@
 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;
-
-    TRACE("socket %04x, ptr %08x, len %d, flags %d\n", s, (unsigned)buf, len, flags);
-#if DEBUG_SOCKADDR
-    if (from)
-        dump_sockaddr(from);
-    else
-        DPRINTF("from = NULL\n");
-#endif
-
-    res=SOCKET_ERROR;
-    if (fd != -1)
-    {
-        struct sockaddr* uaddr;
-        int uaddrlen;
-        int length;
+    DWORD n;
+    WSABUF wsabuf = { len, buf };
+    DWORD dwFlags = flags;

-        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);
-    }
+    if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
+        return SOCKET_ERROR;
     else
-    {
-        SetLastError(WSAENOTSOCK);
-        WARN(" -> WSAENOTSOCK\n");
-    }
-    return res;
+        return n;
 }

 /***********************************************************************
@@ -3404,34 +3340,132 @@


 /***********************************************************************
+ *		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);

-  FIXME( "(%i,%p,%lu,%p,%p,%p,%p,%p,%p: stub\n",
-         s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags,
-         lpFrom, lpFromlen, lpOverlapped, lpCompletionRoutine );
+    fd = _get_sock_fd(s);

-  for( dwCount = 0, rc = 0; dwCount < dwBufferCount; dwCount++ )
-  {
+    if (fd == -1)
+    {
+        err = WSAENOTSOCK;
+        goto error;
+    }

-    if( ( rc = WS_recvfrom(s, lpBuffers[ dwCount ].buf, (INT)lpBuffers[ dwCount ].len,
-                                (INT)*lpFlags, lpFrom, lpFromlen ) ) != 0 )
+    /* FIXME: should this be HeapAlloc() or WS_ALLOC ? */
+    iovec = WS_ALLOC ( dwBufferCount * sizeof (struct iovec) );
+    if ( !iovec )
     {
-       break;
+        err = WSAENOBUFS;
+        goto err_close;
     }

-  }
+    for (i = 0; i < dwBufferCount; i++)
+    {
+        iovec[i].iov_base = lpBuffers[i].buf;
+        iovec[i].iov_len  = lpBuffers[i].len;
+    }

-  return rc;
-}
+    msghdr.msg_name = NULL;

+    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 -ru -X diffignore CVS/wine/dlls/winsock/ws2_32.spec MW/wine/dlls/winsock/ws2_32.spec
--- CVS/wine/dlls/winsock/ws2_32.spec	Mon Jan  7 12:42:08 2002
+++ MW/wine/dlls/winsock/ws2_32.spec	Mon Jan  7 12:55:37 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