Fixed handling of deferred connections in WSAAccept().
This commit is contained in:
parent
801e30071a
commit
d15bf1c0fe
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
111
server/sock.c
111
server/sock.c
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue