Send message for WSAAsyncSelect sockets directly from the server,
instead of using the service thread. Finished separation of ws2_32.
diff --git a/dlls/winsock/socket.c b/dlls/winsock/socket.c
index 379e28d..b2c50ac 100644
--- a/dlls/winsock/socket.c
+++ b/dlls/winsock/socket.c
@@ -104,9 +104,7 @@
#include "wsipx.h"
#include "wine/winsock16.h"
#include "winnt.h"
-#include "services.h"
#include "wine/server.h"
-#include "file.h"
#include "wine/debug.h"
@@ -140,14 +138,10 @@
#define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
#define WS_MAX_UDP_DATAGRAM 1024
-#define WS_ACCEPT_QUEUE 6
-
#define PROCFS_NETDEV_FILE "/proc/net/dev" /* Points to the file in the /proc fs
that lists the network devices.
Do we need an #ifdef LINUX for this? */
-static volatile HANDLE accept_old[WS_ACCEPT_QUEUE], accept_new[WS_ACCEPT_QUEUE];
-
static void *he_buffer; /* typecast for Win16/32 ws_hostent */
static SEGPTR he_buffer_seg;
static void *se_buffer; /* typecast for Win16/32 ws_servent */
@@ -224,23 +218,6 @@
*/
static int opentype = 0;
-/* Permutation of 0..FD_MAX_EVENTS - 1 representing the order in which we post
- * messages if there are multiple events. Used in WINSOCK_DoAsyncEvent. The
- * problem is if there is both a FD_CONNECT event and, say, an FD_READ event
- * available on the same socket, we want to notify the app of the connect event
- * first. Otherwise it may discard the read event because it thinks it hasn't
- * connected yet.
- */
-static const int event_bitorder[FD_MAX_EVENTS] = {
- FD_CONNECT_BIT,
- FD_ACCEPT_BIT,
- FD_OOB_BIT,
- FD_WRITE_BIT,
- FD_READ_BIT,
- FD_CLOSE_BIT,
- 6, 7, 8, 9 /* leftovers */
-};
-
/* set last error code from NT status without mapping WSA errors */
inline static unsigned int set_error( unsigned int err )
{
@@ -255,12 +232,12 @@
static char* check_buffer(int size);
-static int _get_sock_fd(SOCKET s)
+inline static int _get_sock_fd(SOCKET s)
{
- int fd = FILE_GetUnixHandle( s, GENERIC_READ );
- if (fd == -1)
- FIXME("handle %d is not a socket (GLE %ld)\n",s,GetLastError());
- return fd;
+ int fd;
+
+ if (set_error( wine_server_handle_to_fd( s, GENERIC_READ, &fd, NULL, NULL ) )) return -1;
+ return fd;
}
static void _enable_event(SOCKET s, unsigned int event,
@@ -284,7 +261,6 @@
{
req->handle = s;
req->service = FALSE;
- req->s_event = 0;
req->c_event = 0;
wine_server_call( req );
ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
@@ -300,7 +276,6 @@
{
req->handle = s;
req->service = FALSE;
- req->s_event = 0;
req->c_event = 0;
wine_server_call( req );
ret = reply->mask;
@@ -324,7 +299,6 @@
{
req->handle = s;
req->service = FALSE;
- req->s_event = 0;
req->c_event = 0;
wine_server_set_reply( req, events, sizeof(events) );
wine_server_call( req );
@@ -790,20 +764,6 @@
#define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
#endif
-static void ws2_async_accept(SOCKET s, SOCKET as)
-{
- int q;
- /* queue socket for WSAAsyncSelect */
- for (q=0; q<WS_ACCEPT_QUEUE; q++)
- if (InterlockedCompareExchange((LONG *)&accept_old[q], s, 0) == 0)
- break;
- if (q<WS_ACCEPT_QUEUE)
- accept_new[q] = as;
- else
- ERR("accept queue too small\n");
- /* now signal our AsyncSelect handler */
- _enable_event(s, FD_WINE_SERVEVENT, 0, 0);
-}
/**********************************************************************/
@@ -965,10 +925,7 @@
SERVER_END_REQ;
if (as)
{
- unsigned omask = _get_sock_mask( s );
WS_getpeername(as, addr, addrlen32);
- if (omask & FD_WINE_SERVEVENT)
- ws2_async_accept(s, as);
return as;
}
}
@@ -2727,7 +2684,6 @@
{
req->handle = s;
req->service = TRUE;
- req->s_event = 0;
req->c_event = hEvent;
wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
@@ -2752,6 +2708,8 @@
req->handle = s;
req->mask = lEvent;
req->event = hEvent;
+ req->window = 0;
+ req->msg = 0;
ret = wine_server_call( req );
}
SERVER_END_REQ;
@@ -2761,117 +2719,27 @@
}
/***********************************************************************
- * WINSOCK_DoAsyncSelect
- */
-VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
-{
- ws_select_info *info = (ws_select_info*)ptr;
- unsigned int i, j, pmask, orphan = FALSE;
- int errors[FD_MAX_EVENTS];
-
- TRACE("socket %08x, event %08x\n", info->sock, info->event);
- SetLastError(0);
- SERVER_START_REQ( get_socket_event )
- {
- req->handle = info->sock;
- req->service = TRUE;
- req->s_event = info->event; /* <== avoid race conditions */
- req->c_event = info->event;
- wine_server_set_reply( req, errors, sizeof(errors) );
- set_error( wine_server_call(req) );
- pmask = reply->pmask;
- }
- SERVER_END_REQ;
- if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
- {
- /* orphaned event (socket closed or something) */
- pmask = FD_WINE_SERVEVENT;
- orphan = TRUE;
- }
-
- /* check for accepted sockets that needs to inherit WSAAsyncSelect */
- if (pmask & FD_WINE_SERVEVENT) {
- int q;
- for (q=0; q<WS_ACCEPT_QUEUE; q++)
- if (accept_old[q] == info->sock) {
- /* there's only one service thread per process, no lock necessary */
- HANDLE as = accept_new[q];
- if (as) {
- accept_new[q] = 0;
- accept_old[q] = 0;
- WSAAsyncSelect(as, info->hWnd, info->uMsg, info->lEvent);
- }
- }
- pmask &= ~FD_WINE_SERVEVENT;
- }
- /* dispatch network events, but use the order in the event_bitorder
- * array.
- */
- for (i=0; i<FD_MAX_EVENTS; i++) {
- j = event_bitorder[i];
- if (pmask & (1<<j)) {
- TRACE("post: event bit %d, error %d\n", j, errors[j]);
- PostMessageA(info->hWnd, info->uMsg, info->sock,
- WSAMAKESELECTREPLY(1<<j, errors[j]));
- }
- }
- /* cleanup */
- if (orphan)
- {
- TRACE("orphaned event, self-destructing\n");
- /* SERVICE_Delete closes the event object */
- SERVICE_Delete( info->service );
- WS_FREE(info);
- }
-}
-
-/***********************************************************************
* WSAAsyncSelect (WS2_32.101)
*/
INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
{
- int fd = _get_sock_fd(s);
+ int ret;
- TRACE("%04x, hWnd %04x, uMsg %08x, event %08x\n",
- (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
- if (fd != -1)
+ TRACE("%x, hWnd %x, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
+
+ SERVER_START_REQ( set_socket_event )
{
- close(fd);
- if( lEvent )
- {
- ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
- if( info )
- {
- HANDLE hObj = CreateEventA( NULL, TRUE, FALSE, NULL );
- INT err;
-
- info->sock = s;
- info->event = hObj;
- info->hWnd = hWnd;
- info->uMsg = uMsg;
- info->lEvent = lEvent;
- info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
-
- err = WSAEventSelect( s, hObj, lEvent | FD_WINE_SERVEVENT );
- if (err) {
- /* SERVICE_Delete closes the event object */
- SERVICE_Delete( info->service );
- WS_FREE(info);
- return err;
- }
-
- return 0; /* success */
- }
- else SetLastError(WSAENOBUFS);
- }
- else
- {
- WSAEventSelect(s, 0, 0);
- return 0;
- }
- }
- else SetLastError(WSAEINVAL);
- return SOCKET_ERROR;
+ req->handle = s;
+ req->mask = lEvent;
+ req->event = 0;
+ req->window = hWnd;
+ req->msg = uMsg;
+ ret = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+ if (!ret) return 0;
+ SetLastError(WSAEINVAL);
+ return SOCKET_ERROR;
}
/***********************************************************************