Commit 60f8ddbf authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

server: Create ifchange async queue on socket fd.

parent 93863d25
...@@ -8345,12 +8345,15 @@ static void test_sioAddressListChange(void) ...@@ -8345,12 +8345,15 @@ static void test_sioAddressListChange(void)
{ {
struct sockaddr_in bindAddress; struct sockaddr_in bindAddress;
struct in_addr net_address; struct in_addr net_address;
WSAOVERLAPPED overlapped; WSAOVERLAPPED overlapped, *olp;
struct hostent *h; struct hostent *h;
DWORD num_bytes, error, tick; DWORD num_bytes, error, tick;
SOCKET sock, sock2, sock3; SOCKET sock, sock2, sock3;
WSAEVENT event2, event3; WSAEVENT event2, event3;
HANDLE io_port;
ULONG_PTR key;
int acount; int acount;
BOOL bret;
int ret; int ret;
/* Use gethostbyname to find the list of local network interfaces */ /* Use gethostbyname to find the list of local network interfaces */
...@@ -8465,8 +8468,33 @@ static void test_sioAddressListChange(void) ...@@ -8465,8 +8468,33 @@ static void test_sioAddressListChange(void)
ok (ret == SOCKET_ERROR, "WSAIoctl(SIO_ADDRESS_LIST_CHANGE) failed with error %d\n", error); ok (ret == SOCKET_ERROR, "WSAIoctl(SIO_ADDRESS_LIST_CHANGE) failed with error %d\n", error);
ok (error == WSAEWOULDBLOCK, "expected 10035, got %d\n", error); ok (error == WSAEWOULDBLOCK, "expected 10035, got %d\n", error);
io_port = CreateIoCompletionPort( (HANDLE)sock, NULL, 0, 0 );
ok (io_port != NULL, "failed to create completion port %u\n", GetLastError());
set_blocking(sock, FALSE);
memset(&overlapped, 0, sizeof(overlapped));
SetLastError(0xdeadbeef);
ret = WSAIoctl(sock, SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, &num_bytes, &overlapped, NULL);
error = GetLastError();
ok (ret == SOCKET_ERROR, "WSAIoctl(SIO_ADDRESS_LIST_CHANGE) failed with error %u\n", error);
ok (error == ERROR_IO_PENDING, "expected ERROR_IO_PENDING got %u\n", error);
olp = (WSAOVERLAPPED *)0xdeadbeef;
bret = GetQueuedCompletionStatus( io_port, &num_bytes, &key, &olp, 0 );
ok(!bret, "failed to get completion status %u\n", bret);
ok(GetLastError() == WAIT_TIMEOUT, "Last error was %d\n", GetLastError());
ok(!olp, "Overlapped structure is at %p\n", olp);
closesocket(sock); closesocket(sock);
olp = (WSAOVERLAPPED *)0xdeadbeef;
bret = GetQueuedCompletionStatus( io_port, &num_bytes, &key, &olp, 0 );
ok(!bret, "failed to get completion status %u\n", bret);
ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %u\n", GetLastError());
ok(olp == &overlapped, "Overlapped structure is at %p\n", olp);
CloseHandle(io_port);
/* Misuse of the API by using a blocking socket and not using an overlapped structure, /* Misuse of the API by using a blocking socket and not using an overlapped structure,
* this leads to a hang forever. */ * this leads to a hang forever. */
if (0) if (0)
......
...@@ -606,7 +606,9 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, ...@@ -606,7 +606,9 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type,
static void sock_reselect_async( struct fd *fd, struct async_queue *queue ) static void sock_reselect_async( struct fd *fd, struct async_queue *queue )
{ {
struct sock *sock = get_fd_user( fd ); struct sock *sock = get_fd_user( fd );
sock_reselect( sock ); /* ignore reselect on ifchange queue */
if (sock->ifchange_q != queue)
sock_reselect( sock );
} }
static int sock_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb ) static int sock_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb )
...@@ -640,6 +642,7 @@ static void sock_destroy( struct object *obj ) ...@@ -640,6 +642,7 @@ static void sock_destroy( struct object *obj )
free_async_queue( sock->read_q ); free_async_queue( sock->read_q );
free_async_queue( sock->write_q ); free_async_queue( sock->write_q );
async_wake_up( sock->ifchange_q, STATUS_CANCELLED );
sock_destroy_ifchange_q( sock ); sock_destroy_ifchange_q( sock );
if (sock->event) release_object( sock->event ); if (sock->event) release_object( sock->event );
if (sock->fd) if (sock->fd)
...@@ -973,7 +976,6 @@ static void ifchange_destroy( struct object *obj ); ...@@ -973,7 +976,6 @@ static void ifchange_destroy( struct object *obj );
static int ifchange_get_poll_events( struct fd *fd ); static int ifchange_get_poll_events( struct fd *fd );
static void ifchange_poll_event( struct fd *fd, int event ); static void ifchange_poll_event( struct fd *fd, int event );
static void ifchange_reselect_async( struct fd *fd, struct async_queue *queue );
struct ifchange struct ifchange
{ {
...@@ -1014,7 +1016,7 @@ static const struct fd_ops ifchange_fd_ops = ...@@ -1014,7 +1016,7 @@ static const struct fd_ops ifchange_fd_ops =
no_fd_flush, /* flush */ no_fd_flush, /* flush */
no_fd_ioctl, /* ioctl */ no_fd_ioctl, /* ioctl */
NULL, /* queue_async */ NULL, /* queue_async */
ifchange_reselect_async, /* reselect_async */ NULL, /* reselect_async */
NULL /* cancel_async */ NULL /* cancel_async */
}; };
...@@ -1096,11 +1098,6 @@ static void ifchange_poll_event( struct fd *fd, int event ) ...@@ -1096,11 +1098,6 @@ static void ifchange_poll_event( struct fd *fd, int event )
if (status != STATUS_PENDING) ifchange_wake_up( ifchange, status ); if (status != STATUS_PENDING) ifchange_wake_up( ifchange, status );
} }
static void ifchange_reselect_async( struct fd *fd, struct async_queue *queue )
{
/* do nothing, this object is about to disappear */
}
#endif #endif
/* we only need one of these interface notification objects, all of the sockets dependent upon /* we only need one of these interface notification objects, all of the sockets dependent upon
...@@ -1174,7 +1171,6 @@ static void ifchange_add_sock( struct object *obj, struct sock *sock ) ...@@ -1174,7 +1171,6 @@ static void ifchange_add_sock( struct object *obj, struct sock *sock )
static struct async_queue *sock_get_ifchange_q( struct sock *sock ) static struct async_queue *sock_get_ifchange_q( struct sock *sock )
{ {
struct object *ifchange; struct object *ifchange;
struct fd *fd;
if (sock->ifchange_q) /* reuse existing ifchange_q for this socket */ if (sock->ifchange_q) /* reuse existing ifchange_q for this socket */
return sock->ifchange_q; return sock->ifchange_q;
...@@ -1183,9 +1179,7 @@ static struct async_queue *sock_get_ifchange_q( struct sock *sock ) ...@@ -1183,9 +1179,7 @@ static struct async_queue *sock_get_ifchange_q( struct sock *sock )
return NULL; return NULL;
/* create the ifchange notification queue */ /* create the ifchange notification queue */
fd = get_obj_fd( ifchange ); sock->ifchange_q = create_async_queue( sock->fd );
sock->ifchange_q = create_async_queue( fd );
release_object( fd );
if (!sock->ifchange_q) if (!sock->ifchange_q)
{ {
release_object( ifchange ); release_object( ifchange );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment