PATCH: accept-deferred.diff (5 in series)

Martin Wilck Martin.Wilck at fujitsu-siemens.com
Fri Apr 12 10:20:43 CDT 2002


PATCH: accept-deferred.diff

If a connection request is deferred in a call to WSAAccept(),
a subsequent accept()/WSAAccept() call must return the
previously deferred connection rather than a new one.

The current CVS implementation of WSAAccept is wrong in this respect.
This patch fixes this. Furthermore, it includes a trivial implementation
of WSAConnect().

Patch against: CVS 2002-04-12.

Modified files:
        dlls/winsock:   socket.c, ws2_32.spec
        include/wine:   server_protocol.h
        server:         protocol.def, sock.c, request.h, trace.c

diff -ruNX ignore TMP/wine/dlls/winsock/socket.c MW/wine/dlls/winsock/socket.c
--- TMP/wine/dlls/winsock/socket.c	Tue Apr  9 13:29:12 2002
+++ MW/wine/dlls/winsock/socket.c	Fri Apr 12 14:50:50 2002
@@ -1140,6 +1140,19 @@
 }

 /***********************************************************************
+ *              WSAConnect             (WS2_32.30)
+ */
+int WINAPI WSAConnect ( SOCKET s, const struct WS_sockaddr* name, int namelen,
+                        LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
+                        LPQOS lpSQOS, LPQOS lpGQOS )
+{
+    if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
+        WARN ("unsupported parameters!");
+    return WS_connect ( s, name, namelen );
+}
+
+
+/***********************************************************************
  *		getpeername		(WS2_32.5)
  */
 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
@@ -3420,7 +3433,7 @@
        SOCKET cs;
        SOCKADDR src_addr, dst_addr;

-       TRACE("Socket  %ui, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackD ata %ld\n",
+       TRACE("Socket  %u, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackD ata %ld\n",
                s, addr, addrlen, lpfnCondition, dwCallbackData);


@@ -3451,7 +3464,14 @@
                                addr = memcpy(addr, &src_addr, (*addrlen > size) ?  size : *addrlen );
                        return cs;
                case CF_DEFER:
-                       SetLastError(WSATRY_AGAIN);
+                       SERVER_START_REQ ( set_socket_deferred )
+                       {
+                           req->handle = s;
+                           req->deferred = cs;
+                           if ( !wine_server_call_err ( req ) )
+                               SetLastError ( WSATRY_AGAIN );
+                       }
+                       SERVER_END_REQ;
                        return SOCKET_ERROR;
                case CF_REJECT:
                        WS_closesocket(cs);
diff -ruNX ignore TMP/wine/dlls/winsock/ws2_32.spec MW/wine/dlls/winsock/ws2_32.spec
--- TMP/wine/dlls/winsock/ws2_32.spec	Mon Apr  8 10:56:59 2002
+++ MW/wine/dlls/winsock/ws2_32.spec	Fri Apr 12 14:52:57 2002
@@ -42,7 +42,7 @@
 27  stub     WSAAddressToStringA
 28  stub     WSAAddressToStringW
 29  stdcall  WSACloseEvent(long) WSACloseEvent
-30  stub     WSAConnect
+30  stdcall  WSAConnect(long ptr long ptr ptr ptr ptr) WSAConnect
 31  stdcall  WSACreateEvent ()  WSACreateEvent
 32  stub     WSADuplicateSocketA
 33  stub     WSADuplicateSocketW
diff -ruNX ignore TMP/wine/include/wine/server_protocol.h MW/wine/include/wine/server_protocol.h
--- TMP/wine/include/wine/server_protocol.h	Mon Apr  8 10:56:59 2002
+++ MW/wine/include/wine/server_protocol.h	Fri Apr 12 14:25:47 2002
@@ -1001,6 +1001,16 @@
     struct reply_header __header;
 };

+struct set_socket_deferred_request
+{
+    struct request_header __header;
+    handle_t     handle;
+    handle_t     deferred;
+};
+struct set_socket_deferred_reply
+{
+    struct reply_header __header;
+};


 struct alloc_console_request
@@ -2758,6 +2768,7 @@
     REQ_set_socket_event,
     REQ_get_socket_event,
     REQ_enable_socket_event,
+    REQ_set_socket_deferred,
     REQ_alloc_console,
     REQ_free_console,
     REQ_get_console_renderer_events,
@@ -2919,6 +2930,7 @@
     struct set_socket_event_request set_socket_event_request;
     struct get_socket_event_request get_socket_event_request;
     struct enable_socket_event_request enable_socket_event_request;
+    struct set_socket_deferred_request set_socket_deferred_request;
     struct alloc_console_request alloc_console_request;
     struct free_console_request free_console_request;
     struct get_console_renderer_events_request get_console_renderer_events_request;
@@ -3078,6 +3090,7 @@
     struct set_socket_event_reply set_socket_event_reply;
     struct get_socket_event_reply get_socket_event_reply;
     struct enable_socket_event_reply enable_socket_event_reply;
+    struct set_socket_deferred_reply set_socket_deferred_reply;
     struct alloc_console_reply alloc_console_reply;
     struct free_console_reply free_console_reply;
     struct get_console_renderer_events_reply get_console_renderer_events_reply;
@@ -3183,6 +3196,6 @@
     struct get_window_properties_reply get_window_properties_reply;
 };

-#define SERVER_PROTOCOL_VERSION 78
+#define SERVER_PROTOCOL_VERSION 79

 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff -ruNX ignore TMP/wine/server/protocol.def MW/wine/server/protocol.def
--- TMP/wine/server/protocol.def	Mon Apr  8 10:56:59 2002
+++ MW/wine/server/protocol.def	Fri Apr 12 14:18:38 2002
@@ -746,6 +746,10 @@
     unsigned int cstate;        /* status bits to clear */
 @END

+ at REQ(set_socket_deferred)
+    handle_t     handle;        /* handle to the socket */
+    handle_t     deferred;      /* handle to the socket for which accept() is deferred */
+ at END

 /* Allocate a console (only used by a console renderer) */
 @REQ(alloc_console)
diff -ruNX ignore TMP/wine/server/request.h MW/wine/server/request.h
--- TMP/wine/server/request.h	Fri Apr  5 12:21:25 2002
+++ MW/wine/server/request.h	Fri Apr 12 14:16:35 2002
@@ -152,6 +152,7 @@
 DECL_HANDLER(set_socket_event);
 DECL_HANDLER(get_socket_event);
 DECL_HANDLER(enable_socket_event);
+DECL_HANDLER(set_socket_deferred);
 DECL_HANDLER(alloc_console);
 DECL_HANDLER(free_console);
 DECL_HANDLER(get_console_renderer_events);
@@ -312,6 +313,7 @@
     (req_handler)req_set_socket_event,
     (req_handler)req_get_socket_event,
     (req_handler)req_enable_socket_event,
+    (req_handler)req_set_socket_deferred,
     (req_handler)req_alloc_console,
     (req_handler)req_free_console,
     (req_handler)req_get_console_renderer_events,
diff -ruNX ignore TMP/wine/server/sock.c MW/wine/server/sock.c
--- TMP/wine/server/sock.c	Tue Apr  2 16:51:51 2002
+++ MW/wine/server/sock.c	Fri Apr 12 14:24:35 2002
@@ -72,6 +72,7 @@
     unsigned int        message;     /* message to send */
     unsigned int        wparam;      /* message wparam (socket handle) */
     int                 errors[FD_MAX_EVENTS]; /* event errors */
+    handle_t            deferred;    /* socket that waits for a deferred accept */
     struct async_queue  read_q;      /* Queue for asynchronous reads */
     struct async_queue  write_q;     /* Queue for asynchronous writes */
 };
@@ -361,6 +362,9 @@

     /* FIXME: special socket shutdown stuff? */

+    if ( sock->deferred )
+        close_handle ( current->process, sock->deferred, NULL );
+
     if ( sock->flags & WSA_FLAG_OVERLAPPED )
     {
         destroy_async_queue ( &sock->read_q );
@@ -394,18 +398,19 @@
     sock->window  = 0;
     sock->message = 0;
     sock->wparam  = 0;
-    sock_reselect( sock );
-    clear_error();
+    sock->deferred = 0;
     if (sock->flags & WSA_FLAG_OVERLAPPED)
     {
         init_async_queue (&sock->read_q);
         init_async_queue (&sock->write_q);
     }
+    sock_reselect( sock );
+    clear_error();
     return &sock->obj;
 }

 /* accept a socket (creates a new fd) */
-static struct sock *accept_socket( handle_t handle )
+static struct sock *accept_socket( handle_t handle, handle_t *accept_handle, unsigned int access, int inherit )
 {
     struct sock *acceptsock;
     struct sock *sock;
@@ -417,42 +422,52 @@
                                       GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops);
     if (!sock)
     	return NULL;
-    /* Try to accept(2). We can't be safe that this an already connected socket
-     * or that accept() is allowed on it. In those cases we will get -1/errno
-     * return.
-     */
-    slen = sizeof(saddr);
-    acceptfd = accept(sock->obj.fd,&saddr,&slen);
-    if (acceptfd==-1) {
-    	sock_set_error();
-        release_object( sock );
-	return NULL;
-    }
-    if (!(acceptsock = alloc_object( &sock_ops, -1 )))
-    {
-        release_object( sock );
-        return NULL;
-    }
+    if ( sock->deferred ) {
+        acceptsock = (struct sock*)get_handle_obj( current->process, sock->deferred,
+                                                   GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops );
+        *accept_handle = sock->deferred;
+        sock->deferred = 0;
+    } else {
+
+        /* Try to accept(2). We can't be safe that this an already connected socket
+         * or that accept() is allowed on it. In those cases we will get -1/errno
+         * return.
+         */
+        slen = sizeof(saddr);
+        acceptfd = accept(sock->obj.fd,&saddr,&slen);
+        if (acceptfd==-1) {
+            sock_set_error();
+            release_object( sock );
+            return NULL;
+        }
+        if (!(acceptsock = alloc_object( &sock_ops, -1 )))
+        {
+            release_object( sock );
+            return NULL;
+        }

-    /* newly created socket gets the same properties of the listening socket */
-    fcntl(acceptfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */
-    acceptsock->obj.fd = acceptfd;
-    acceptsock->state  = FD_WINE_CONNECTED|FD_READ|FD_WRITE;
-    if (sock->state & FD_WINE_NONBLOCKING)
-        acceptsock->state |= FD_WINE_NONBLOCKING;
-    acceptsock->mask    = sock->mask;
-    acceptsock->hmask   = 0;
-    acceptsock->pmask   = 0;
-    acceptsock->event   = NULL;
-    acceptsock->window  = sock->window;
-    acceptsock->message = sock->message;
-    acceptsock->wparam  = 0;
-    if (sock->event) acceptsock->event = (struct event *)grab_object( sock->event );
-    acceptsock->flags = sock->flags;
-    if ( acceptsock->flags & WSA_FLAG_OVERLAPPED )
-    {
-	init_async_queue ( &acceptsock->read_q );
-	init_async_queue ( &acceptsock->write_q );
+        /* newly created socket gets the same properties of the listening socket */
+        fcntl(acceptfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */
+        acceptsock->obj.fd = acceptfd;
+        acceptsock->state  = FD_WINE_CONNECTED|FD_READ|FD_WRITE;
+        if (sock->state & FD_WINE_NONBLOCKING)
+            acceptsock->state |= FD_WINE_NONBLOCKING;
+        acceptsock->mask    = sock->mask;
+        acceptsock->hmask   = 0;
+        acceptsock->pmask   = 0;
+        acceptsock->event   = NULL;
+        acceptsock->window  = sock->window;
+        acceptsock->message = sock->message;
+        acceptsock->wparam  = 0;
+        if (sock->event) acceptsock->event = (struct event *)grab_object( sock->event );
+        acceptsock->flags = sock->flags;
+        acceptsock->deferred = 0;
+        if ( acceptsock->flags & WSA_FLAG_OVERLAPPED )
+        {
+            init_async_queue ( &acceptsock->read_q );
+            init_async_queue ( &acceptsock->write_q );
+        }
+        *accept_handle = alloc_handle( current->process, &acceptsock->obj, access, inherit );
     }

     clear_error();
@@ -552,9 +567,8 @@
     struct sock *sock;

     reply->handle = 0;
-    if ((sock = accept_socket( req->lhandle )) != NULL)
+    if ( (sock = accept_socket( req->lhandle, &reply->handle, req->access, req->inherit )) != NULL )
     {
-        reply->handle = alloc_handle( current->process, &sock->obj, req->access, req->inherit );
         sock->wparam = reply->handle;  /* wparam for message is the socket handle */
         sock_reselect( sock );
         release_object( &sock->obj );
@@ -645,4 +659,27 @@
     sock->state &= ~req->cstate;
     sock_reselect( sock );
     release_object( &sock->obj );
+}
+
+DECL_HANDLER(set_socket_deferred)
+{
+    struct sock *sock;
+
+    sock=(struct sock*)get_handle_obj( current->process,req->handle,
+                                       GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops );
+    if (!sock)
+    {
+        set_error ( WSAENOTSOCK );
+        return;
+    }
+    sock->deferred = req->deferred;
+        /* duplicate_handle ( current->process, req->deferred, current->process,
+           GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE, TRUE, 0 ); */
+    if ( !sock->deferred )
+    {
+        release_object ( sock );
+        set_error ( WSAENOTSOCK );
+        return;
+    }
+    release_object ( sock );
 }
diff -ruNX ignore TMP/wine/server/trace.c MW/wine/server/trace.c
--- TMP/wine/server/trace.c	Mon Apr  8 10:56:59 2002
+++ MW/wine/server/trace.c	Fri Apr 12 14:16:35 2002
@@ -943,6 +943,12 @@
     fprintf( stderr, " cstate=%08x", req->cstate );
 }

+static void dump_set_socket_deferred_request( const struct set_socket_deferred_request *req )
+{
+    fprintf( stderr, " handle=%d,", req->handle );
+    fprintf( stderr, " deferred=%d", req->deferred );
+}
+
 static void dump_alloc_console_request( const struct alloc_console_request *req )
 {
     fprintf( stderr, " access=%08x,", req->access );
@@ -2215,6 +2221,7 @@
     (dump_func)dump_set_socket_event_request,
     (dump_func)dump_get_socket_event_request,
     (dump_func)dump_enable_socket_event_request,
+    (dump_func)dump_set_socket_deferred_request,
     (dump_func)dump_alloc_console_request,
     (dump_func)dump_free_console_request,
     (dump_func)dump_get_console_renderer_events_request,
@@ -2372,6 +2379,7 @@
     (dump_func)0,
     (dump_func)dump_get_socket_event_reply,
     (dump_func)0,
+    (dump_func)0,
     (dump_func)dump_alloc_console_reply,
     (dump_func)0,
     (dump_func)dump_get_console_renderer_events_reply,
@@ -2529,6 +2537,7 @@
     "set_socket_event",
     "get_socket_event",
     "enable_socket_event",
+    "set_socket_deferred",
     "alloc_console",
     "free_console",
     "get_console_renderer_events",







More information about the wine-devel mailing list