server: Add socket-side support for the interface change notification object.
This commit is contained in:
parent
1239663fcb
commit
315de61bb2
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue