Fixed handling of deferred connections in WSAAccept().

This commit is contained in:
Martin Wilck 2002-04-23 22:03:42 +00:00 committed by Alexandre Julliard
parent 801e30071a
commit d15bf1c0fe
7 changed files with 128 additions and 42 deletions

View file

@ -1138,6 +1138,19 @@ INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct WS_sockaddr *name, INT16 namel
return (INT16)WS_connect( s, name, namelen );
}
/***********************************************************************
* 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 )
FIXME ("unsupported parameters!\n");
return WS_connect ( s, name, namelen );
}
/***********************************************************************
* getpeername (WS2_32.5)
*/
@ -3419,7 +3432,7 @@ SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
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, dwCallbackData %ld\n",
s, addr, addrlen, lpfnCondition, dwCallbackData);
@ -3450,7 +3463,17 @@ SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
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 );
CloseHandle ( cs );
}
}
SERVER_END_REQ;
return SOCKET_ERROR;
case CF_REJECT:
WS_closesocket(cs);

View file

@ -42,7 +42,7 @@ debug_channels (winsock)
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

View file

@ -1001,6 +1001,16 @@ struct enable_socket_event_reply
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 @@ enum request
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 @@ union generic_request
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 @@ union generic_reply
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 @@ union generic_reply
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 */

View file

@ -746,6 +746,10 @@ enum fd_type
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)

View file

@ -152,6 +152,7 @@ DECL_HANDLER(accept_socket);
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 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(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,

View file

@ -72,6 +72,7 @@ struct sock
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 @@ static void sock_destroy( struct object *obj )
/* 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 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
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 @@ static struct sock *accept_socket( handle_t handle )
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 @@ DECL_HANDLER(enable_socket_event)
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 );
}

View file

@ -943,6 +943,12 @@ static void dump_enable_socket_event_request( const struct enable_socket_event_r
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 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(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 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(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 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"set_socket_event",
"get_socket_event",
"enable_socket_event",
"set_socket_deferred",
"alloc_console",
"free_console",
"get_console_renderer_events",