Fixed handling of deferred connections in WSAAccept().
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 );
+}