Erich E. Hoover : server: Add socket-side support for the interface change notification object.
Alexandre Julliard
julliard at wine.codeweavers.com
Tue Feb 10 10:46:04 CST 2015
Module: wine
Branch: master
Commit: 315de61bb20a17862911c2e77df7ab25c794e57c
URL: http://source.winehq.org/git/wine.git/?a=commit;h=315de61bb20a17862911c2e77df7ab25c794e57c
Author: Erich E. Hoover <erich.e.hoover at wine-staging.com>
Date: Tue May 6 08:39:18 2014 -0600
server: Add socket-side support for the interface change notification object.
---
server/sock.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 86 insertions(+), 1 deletion(-)
diff --git a/server/sock.c b/server/sock.c
index 6a75934..8c8db87 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -110,12 +110,18 @@ struct sock
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 */
+ struct async_queue *ifchange_q; /* queue for interface change notifications */
+ struct object *ifchange_obj; /* the interface change notification object */
+ struct list ifchange_entry; /* entry in ifchange notification list */
};
static void sock_dump( struct object *obj, int verbose );
+static void sock_add_ifchange( struct sock *sock, const async_data_t *async_data );
static int sock_signaled( struct object *obj, struct wait_queue_entry *entry );
static struct fd *sock_get_fd( struct object *obj );
static void sock_destroy( struct object *obj );
+static struct async_queue *sock_get_ifchange_q( struct sock *sock );
+static void sock_destroy_ifchange_q( struct sock *sock );
static int sock_get_poll_events( struct fd *fd );
static void sock_poll_event( struct fd *fd, int event );
@@ -534,7 +540,8 @@ obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *a
switch(code)
{
case WS_SIO_ADDRESS_LIST_CHANGE:
- /* intentional fallthrough, not yet supported */
+ sock_add_ifchange( sock, async_data );
+ return 0;
default:
set_error( STATUS_NOT_SUPPORTED );
return 0;
@@ -615,6 +622,7 @@ static void sock_destroy( struct object *obj )
free_async_queue( sock->read_q );
free_async_queue( sock->write_q );
+ sock_destroy_ifchange_q( sock );
if (sock->event) release_object( sock->event );
if (sock->fd)
{
@@ -642,6 +650,8 @@ static void init_sock(struct sock *sock)
sock->deferred = NULL;
sock->read_q = NULL;
sock->write_q = NULL;
+ sock->ifchange_q = NULL;
+ sock->ifchange_obj = NULL;
memset( sock->errors, 0, sizeof(sock->errors) );
}
@@ -933,6 +943,81 @@ static void sock_set_error(void)
set_error( sock_get_ntstatus( errno ) );
}
+/* add interface change notification to a socket */
+static void sock_add_ifchange( struct sock *sock, const async_data_t *async_data )
+{
+ struct async_queue *ifchange_q;
+ struct async *async;
+
+ if (!(ifchange_q = sock_get_ifchange_q( sock )))
+ return;
+
+ if (!(async = create_async( current, ifchange_q, async_data )))
+ {
+ if (!async_queued( ifchange_q ))
+ sock_destroy_ifchange_q( sock );
+
+ set_error( STATUS_NO_MEMORY );
+ return;
+ }
+
+ release_object( async );
+ set_error( STATUS_PENDING );
+}
+
+/* stub ifchange object */
+static struct object *get_ifchange( void )
+{
+ set_error( STATUS_NOT_SUPPORTED );
+ return NULL;
+}
+
+/* stub ifchange add socket to list */
+static void ifchange_add_sock( struct object *obj, struct sock *sock )
+{
+}
+
+/* create a new ifchange queue for a specific socket or, if one already exists, reuse the existing one */
+static struct async_queue *sock_get_ifchange_q( struct sock *sock )
+{
+ struct object *ifchange;
+ struct fd *fd;
+
+ if (sock->ifchange_q) /* reuse existing ifchange_q for this socket */
+ return sock->ifchange_q;
+
+ if (!(ifchange = get_ifchange()))
+ return NULL;
+
+ /* create the ifchange notification queue */
+ fd = ifchange->ops->get_fd( ifchange );
+ sock->ifchange_q = create_async_queue( fd );
+ release_object( fd );
+ if (!sock->ifchange_q)
+ {
+ release_object( ifchange );
+ set_error( STATUS_NO_MEMORY );
+ return NULL;
+ }
+
+ /* add the socket to the ifchange notification list */
+ ifchange_add_sock( ifchange, sock );
+ sock->ifchange_obj = ifchange;
+ return sock->ifchange_q;
+}
+
+/* destroy an existing ifchange queue for a specific socket */
+static void sock_destroy_ifchange_q( struct sock *sock )
+{
+ if (sock->ifchange_q)
+ {
+ list_remove( &sock->ifchange_entry );
+ free_async_queue( sock->ifchange_q );
+ sock->ifchange_q = NULL;
+ release_object( sock->ifchange_obj );
+ }
+}
+
/* create a socket */
DECL_HANDLER(create_socket)
{
More information about the wine-cvs
mailing list