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