Fixed handling of deferred connections in WSAAccept().
diff --git a/server/protocol.def b/server/protocol.def
index ba96ea7..e151470 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -746,6 +746,10 @@
unsigned int cstate; /* status bits to clear */
@END
+@REQ(set_socket_deferred)
+ handle_t handle; /* handle to the socket */
+ handle_t deferred; /* handle to the socket for which accept() is deferred */
+@END
/* Allocate a console (only used by a console renderer) */
@REQ(alloc_console)
diff --git a/server/request.h b/server/request.h
index 99bba36..f14b26e 100644
--- a/server/request.h
+++ b/server/request.h
@@ -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 --git a/server/sock.c b/server/sock.c
index 3d1e139..d9c0be7 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -72,6 +72,7 @@
unsigned int message; /* message to send */
unsigned int wparam; /* message wparam (socket handle) */
int errors[FD_MAX_EVENTS]; /* event errors */
+ struct sock* 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 )
+ release_object ( sock->deferred );
+
if ( sock->flags & WSA_FLAG_OVERLAPPED )
{
destroy_async_queue ( &sock->read_q );
@@ -394,13 +398,14 @@
sock->window = 0;
sock->message = 0;
sock->wparam = 0;
- sock_reselect( sock );
- clear_error();
+ sock->deferred = NULL;
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;
}
@@ -417,44 +422,51 @@
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;
- }
- /* 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 );
- }
+ if ( sock->deferred ) {
+ acceptsock = sock->deferred;
+ sock->deferred = NULL;
+ } 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;
+ acceptsock->deferred = 0;
+ if ( acceptsock->flags & WSA_FLAG_OVERLAPPED )
+ {
+ init_async_queue ( &acceptsock->read_q );
+ init_async_queue ( &acceptsock->write_q );
+ }
+ }
clear_error();
sock->pmask &= ~FD_ACCEPT;
sock->hmask &= ~FD_ACCEPT;
@@ -646,3 +658,26 @@
sock_reselect( sock );
release_object( &sock->obj );
}
+
+DECL_HANDLER(set_socket_deferred)
+{
+ struct sock *sock, *acceptsock;
+
+ sock=(struct sock*)get_handle_obj( current->process,req->handle,
+ GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops );
+ if ( !sock )
+ {
+ set_error ( WSAENOTSOCK );
+ return;
+ }
+ acceptsock = (struct sock*)get_handle_obj( current->process,req->deferred,
+ GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops );
+ if ( !acceptsock )
+ {
+ release_object ( sock );
+ set_error ( WSAENOTSOCK );
+ return;
+ }
+ sock->deferred = acceptsock;
+ release_object ( sock );
+}
diff --git a/server/trace.c b/server/trace.c
index 00eb57d..b577e71 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -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",