[PATCH] Move send() functionality to WS2_32 code

Martin Wilck Martin.Wilck at fujitsu-siemens.com
Thu Apr 4 06:47:56 CST 2002


PATCH: Move send() functionality to WS2_32 code

In short, does the same to send() that the previous patch did to recv().

For the send() family of functions, WSASendTo() becomes the work horse.
All other functions (WSASend(), send(), sendto(), ...) are only wrappers
around WSASendTo().

To provide the scatter/gather functionality of WSASendTo(), the Unix system call
used as backend is sendmsg() rather than sendto().

Patch against:  Wine CVS 2002-04-03, with my previous patch (recv) applied.

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 TMP/wine/dlls/winsock/socket.c MW/wine/dlls/winsock/socket.c
--- TMP/wine/dlls/winsock/socket.c	Thu Apr  4 10:58:53 2002
+++ MW/wine/dlls/winsock/socket.c	Thu Apr  4 11:01:03 2002
@@ -1944,34 +1944,13 @@
  */
 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
 {
-    int fd = _get_sock_fd(s);
+    DWORD n;
+    WSABUF wsabuf = { len, (char*) buf };

-    TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags);
-    if (fd != -1)
-    {
-	int	length;
-
-	if (_is_blocking(s))
-	{
-	    /* block here */
-	    /* FIXME: exceptfds */
-	    do_block(fd, 2);
-	}
-	if ((length = send(fd, buf, len, flags)) < 0 )
-	{
-	    SetLastError(wsaErrno());
-	    if( GetLastError() == WSAEWOULDBLOCK )
-		_enable_event(s, FD_WRITE, 0, 0);
-	}
-	else
-	{
-	    close(fd);
-	    return length;
-	}
-	close(fd);
-    }
-    else SetLastError(WSAENOTSOCK);
-    return SOCKET_ERROR;
+    if ( WSASendTo ( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
+        return SOCKET_ERROR;
+    else
+        return n;
 }

 /***********************************************************************
@@ -1982,43 +1961,106 @@
                     LPWSAOVERLAPPED lpOverlapped,
                     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
 {
-  INT iFlags = 0;
-  INT rc = 0;
-  DWORD dwCount;
-
-  /* Overlapped is not supported or checked for */
-  FIXME( "(%u,%p,0x%lx,%p,0x%lx,%p,%p): semi stub\n",
-           s, lpBuffers, dwBufferCount, lpNumberOfBytesSent,
-           dwFlags, lpOverlapped, lpCompletionRoutine );
-
-  /* Convert setup flags */
-  if( dwFlags & MSG_DONTROUTE )
-  {
-    iFlags |= MSG_DONTROUTE;
-  }
-
-  if( dwFlags & MSG_OOB )
-  {
-    iFlags |= MSG_OOB;
-  }
-
-  /* Indicate nothing yet sent */
-  *lpNumberOfBytesSent = 0;
-
-  /* Send all buffers with the same flags */
-  for(dwCount = 0; dwCount < dwBufferCount; dwCount++ )
-  {
-    if( ( rc = WS_send( s, lpBuffers[ dwCount ].buf,
-                             lpBuffers[ dwCount ].len, iFlags ) ) != 0 )
+    return WSASendTo ( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
+                       NULL, 0, lpOverlapped, lpCompletionRoutine );
+}
+
+/***********************************************************************
+ *		WSASendTo		(WS2_32.74)
+ */
+INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
+                      LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
+                      const struct WS_sockaddr *to, int tolen,
+                      LPWSAOVERLAPPED lpOverlapped,
+                      LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
+{
+    int i, n, fd, err = WSAENOTSOCK;
+    struct iovec* iovec;
+    struct msghdr msghdr;
+
+    TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
+           s, lpBuffers, dwBufferCount, dwFlags,
+           to, tolen, lpOverlapped, lpCompletionRoutine);
+
+    fd = _get_sock_fd(s);
+
+    if ( fd == -1 )
+        goto error;
+
+    iovec = WS_ALLOC ( dwBufferCount * sizeof (struct iovec) );
+
+    if ( !iovec )
+    {
+        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;
+    }
+
+    msghdr.msg_name = NULL;
+
+    if (to)
+    {
+#if DEBUG_SOCKADDR
+        dump_sockaddr (to);
+#endif
+        msghdr.msg_name = (void*) ws_sockaddr_ws2u (to, tolen, &msghdr.msg_namelen);
+        if ( !msghdr.msg_name )
+        {
+            err = WSAEFAULT;
+            goto err_free;
+        }
+    }
+    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))
+    {
+        /* FIXME: exceptfds? */
+        do_block(fd, 2);
+    }
+
+    /* FIXME: can we support MSG_PARTIAL ? How does it relate to sendmsg()'s msg_flags ? */
+
+    if ((n = sendmsg (fd, &msghdr, dwFlags)) == -1)
     {
-      break;
+        err = wsaErrno();
+        if ( err == WSAEWOULDBLOCK )
+            _enable_event (s, FD_WRITE, 0, 0);
+        goto err_free;
     }

-    /* Indicate that we've sent something */
-    *lpNumberOfBytesSent += lpBuffers[ dwCount ].len;
-  }
+    *lpNumberOfBytesSent = n;

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

 /***********************************************************************
@@ -2035,46 +2077,13 @@
 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
                               const struct WS_sockaddr *to, int tolen)
 {
-    int fd = _get_sock_fd(s);
-    int res;
-
-    TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags);
-
-    res=SOCKET_ERROR;
-    if (fd != -1)
-    {
-        const struct sockaddr* uaddr;
-        int uaddrlen;
+    DWORD n;
+    WSABUF wsabuf = { len, (char*) buf };

-        uaddr=ws_sockaddr_ws2u(to,tolen,&uaddrlen);
-        if (uaddr == NULL)
-        {
-            SetLastError(WSAEFAULT);
-        }
-        else
-        {
-            if (_is_blocking(s))
-            {
-                /* block here */
-                /* FIXME: exceptfds */
-                do_block(fd, 2);
-            }
-            res=sendto(fd, buf, len, flags, uaddr, uaddrlen);
-            if (res < 0 )
-            {
-                SetLastError(wsaErrno());
-                if( GetLastError() == WSAEWOULDBLOCK )
-                    _enable_event(s, FD_WRITE, 0, 0);
-            }
-            ws_sockaddr_free(uaddr,to);
-        }
-        close(fd);
-    }
+    if ( WSASendTo (s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
+        return SOCKET_ERROR;
     else
-    {
-        SetLastError(WSAENOTSOCK);
-    }
-    return res;
+        return n;
 }

 /***********************************************************************
diff -ruNX diffignore TMP/wine/dlls/winsock/ws2_32.spec MW/wine/dlls/winsock/ws2_32.spec
--- TMP/wine/dlls/winsock/ws2_32.spec	Thu Apr  4 10:58:53 2002
+++ MW/wine/dlls/winsock/ws2_32.spec	Thu Apr  4 11:01:03 2002
@@ -86,7 +86,7 @@
 71  forward  WSAResetEvent KERNEL32.ResetEvent
 72  stdcall  WSASend(long ptr long ptr long ptr ptr) WSASend
 73  stub     WSASendDisconnect
-74  stub     WSASendTo
+74  stdcall  WSASendTo(long ptr long ptr long ptr long ptr ptr) WSASendTo
 75  stub     WSASetEvent
 76  stub     WSASetServiceA
 77  stub     WSASetServiceW






More information about the wine-devel mailing list