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 );
|
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)
|
* getpeername (WS2_32.5)
|
||||||
*/
|
*/
|
||||||
@ -3419,7 +3432,7 @@ SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
|
|||||||
SOCKET cs;
|
SOCKET cs;
|
||||||
SOCKADDR src_addr, dst_addr;
|
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);
|
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 );
|
addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
|
||||||
return cs;
|
return cs;
|
||||||
case CF_DEFER:
|
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;
|
return SOCKET_ERROR;
|
||||||
case CF_REJECT:
|
case CF_REJECT:
|
||||||
WS_closesocket(cs);
|
WS_closesocket(cs);
|
||||||
|
@ -42,7 +42,7 @@ debug_channels (winsock)
|
|||||||
27 stub WSAAddressToStringA
|
27 stub WSAAddressToStringA
|
||||||
28 stub WSAAddressToStringW
|
28 stub WSAAddressToStringW
|
||||||
29 stdcall WSACloseEvent(long) WSACloseEvent
|
29 stdcall WSACloseEvent(long) WSACloseEvent
|
||||||
30 stub WSAConnect
|
30 stdcall WSAConnect(long ptr long ptr ptr ptr ptr) WSAConnect
|
||||||
31 stdcall WSACreateEvent () WSACreateEvent
|
31 stdcall WSACreateEvent () WSACreateEvent
|
||||||
32 stub WSADuplicateSocketA
|
32 stub WSADuplicateSocketA
|
||||||
33 stub WSADuplicateSocketW
|
33 stub WSADuplicateSocketW
|
||||||
|
@ -1001,6 +1001,16 @@ struct enable_socket_event_reply
|
|||||||
struct reply_header __header;
|
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
|
struct alloc_console_request
|
||||||
@ -2758,6 +2768,7 @@ enum request
|
|||||||
REQ_set_socket_event,
|
REQ_set_socket_event,
|
||||||
REQ_get_socket_event,
|
REQ_get_socket_event,
|
||||||
REQ_enable_socket_event,
|
REQ_enable_socket_event,
|
||||||
|
REQ_set_socket_deferred,
|
||||||
REQ_alloc_console,
|
REQ_alloc_console,
|
||||||
REQ_free_console,
|
REQ_free_console,
|
||||||
REQ_get_console_renderer_events,
|
REQ_get_console_renderer_events,
|
||||||
@ -2919,6 +2930,7 @@ union generic_request
|
|||||||
struct set_socket_event_request set_socket_event_request;
|
struct set_socket_event_request set_socket_event_request;
|
||||||
struct get_socket_event_request get_socket_event_request;
|
struct get_socket_event_request get_socket_event_request;
|
||||||
struct enable_socket_event_request enable_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 alloc_console_request alloc_console_request;
|
||||||
struct free_console_request free_console_request;
|
struct free_console_request free_console_request;
|
||||||
struct get_console_renderer_events_request get_console_renderer_events_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 set_socket_event_reply set_socket_event_reply;
|
||||||
struct get_socket_event_reply get_socket_event_reply;
|
struct get_socket_event_reply get_socket_event_reply;
|
||||||
struct enable_socket_event_reply enable_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 alloc_console_reply alloc_console_reply;
|
||||||
struct free_console_reply free_console_reply;
|
struct free_console_reply free_console_reply;
|
||||||
struct get_console_renderer_events_reply get_console_renderer_events_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;
|
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 */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
@ -746,6 +746,10 @@ enum fd_type
|
|||||||
unsigned int cstate; /* status bits to clear */
|
unsigned int cstate; /* status bits to clear */
|
||||||
@END
|
@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) */
|
/* Allocate a console (only used by a console renderer) */
|
||||||
@REQ(alloc_console)
|
@REQ(alloc_console)
|
||||||
|
@ -152,6 +152,7 @@ DECL_HANDLER(accept_socket);
|
|||||||
DECL_HANDLER(set_socket_event);
|
DECL_HANDLER(set_socket_event);
|
||||||
DECL_HANDLER(get_socket_event);
|
DECL_HANDLER(get_socket_event);
|
||||||
DECL_HANDLER(enable_socket_event);
|
DECL_HANDLER(enable_socket_event);
|
||||||
|
DECL_HANDLER(set_socket_deferred);
|
||||||
DECL_HANDLER(alloc_console);
|
DECL_HANDLER(alloc_console);
|
||||||
DECL_HANDLER(free_console);
|
DECL_HANDLER(free_console);
|
||||||
DECL_HANDLER(get_console_renderer_events);
|
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_set_socket_event,
|
||||||
(req_handler)req_get_socket_event,
|
(req_handler)req_get_socket_event,
|
||||||
(req_handler)req_enable_socket_event,
|
(req_handler)req_enable_socket_event,
|
||||||
|
(req_handler)req_set_socket_deferred,
|
||||||
(req_handler)req_alloc_console,
|
(req_handler)req_alloc_console,
|
||||||
(req_handler)req_free_console,
|
(req_handler)req_free_console,
|
||||||
(req_handler)req_get_console_renderer_events,
|
(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 message; /* message to send */
|
||||||
unsigned int wparam; /* message wparam (socket handle) */
|
unsigned int wparam; /* message wparam (socket handle) */
|
||||||
int errors[FD_MAX_EVENTS]; /* event errors */
|
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 read_q; /* Queue for asynchronous reads */
|
||||||
struct async_queue write_q; /* Queue for asynchronous writes */
|
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? */
|
/* FIXME: special socket shutdown stuff? */
|
||||||
|
|
||||||
|
if ( sock->deferred )
|
||||||
|
release_object ( sock->deferred );
|
||||||
|
|
||||||
if ( sock->flags & WSA_FLAG_OVERLAPPED )
|
if ( sock->flags & WSA_FLAG_OVERLAPPED )
|
||||||
{
|
{
|
||||||
destroy_async_queue ( &sock->read_q );
|
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->window = 0;
|
||||||
sock->message = 0;
|
sock->message = 0;
|
||||||
sock->wparam = 0;
|
sock->wparam = 0;
|
||||||
sock_reselect( sock );
|
sock->deferred = NULL;
|
||||||
clear_error();
|
|
||||||
if (sock->flags & WSA_FLAG_OVERLAPPED)
|
if (sock->flags & WSA_FLAG_OVERLAPPED)
|
||||||
{
|
{
|
||||||
init_async_queue (&sock->read_q);
|
init_async_queue (&sock->read_q);
|
||||||
init_async_queue (&sock->write_q);
|
init_async_queue (&sock->write_q);
|
||||||
}
|
}
|
||||||
|
sock_reselect( sock );
|
||||||
|
clear_error();
|
||||||
return &sock->obj;
|
return &sock->obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,44 +422,51 @@ static struct sock *accept_socket( handle_t handle )
|
|||||||
GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops);
|
GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops);
|
||||||
if (!sock)
|
if (!sock)
|
||||||
return NULL;
|
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 */
|
if ( sock->deferred ) {
|
||||||
fcntl(acceptfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */
|
acceptsock = sock->deferred;
|
||||||
acceptsock->obj.fd = acceptfd;
|
sock->deferred = NULL;
|
||||||
acceptsock->state = FD_WINE_CONNECTED|FD_READ|FD_WRITE;
|
} else {
|
||||||
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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* 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();
|
clear_error();
|
||||||
sock->pmask &= ~FD_ACCEPT;
|
sock->pmask &= ~FD_ACCEPT;
|
||||||
sock->hmask &= ~FD_ACCEPT;
|
sock->hmask &= ~FD_ACCEPT;
|
||||||
@ -646,3 +658,26 @@ DECL_HANDLER(enable_socket_event)
|
|||||||
sock_reselect( sock );
|
sock_reselect( sock );
|
||||||
release_object( &sock->obj );
|
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 );
|
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 )
|
static void dump_alloc_console_request( const struct alloc_console_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " access=%08x,", req->access );
|
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_set_socket_event_request,
|
||||||
(dump_func)dump_get_socket_event_request,
|
(dump_func)dump_get_socket_event_request,
|
||||||
(dump_func)dump_enable_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_alloc_console_request,
|
||||||
(dump_func)dump_free_console_request,
|
(dump_func)dump_free_console_request,
|
||||||
(dump_func)dump_get_console_renderer_events_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)0,
|
||||||
(dump_func)dump_get_socket_event_reply,
|
(dump_func)dump_get_socket_event_reply,
|
||||||
(dump_func)0,
|
(dump_func)0,
|
||||||
|
(dump_func)0,
|
||||||
(dump_func)dump_alloc_console_reply,
|
(dump_func)dump_alloc_console_reply,
|
||||||
(dump_func)0,
|
(dump_func)0,
|
||||||
(dump_func)dump_get_console_renderer_events_reply,
|
(dump_func)dump_get_console_renderer_events_reply,
|
||||||
@ -2529,6 +2537,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||||||
"set_socket_event",
|
"set_socket_event",
|
||||||
"get_socket_event",
|
"get_socket_event",
|
||||||
"enable_socket_event",
|
"enable_socket_event",
|
||||||
|
"set_socket_deferred",
|
||||||
"alloc_console",
|
"alloc_console",
|
||||||
"free_console",
|
"free_console",
|
||||||
"get_console_renderer_events",
|
"get_console_renderer_events",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user