Import QEMU upstream snapshot d2e570c
Upstream: https://gitlab.com/qemu-project/qemu.git Upstream-Commit: d2e570cc0f97b936902a5b1b86b73c0f5998b475
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* QEMU I/O channels memory buffer driver
|
||||
*
|
||||
* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QIO_CHANNEL_BUFFER_H
|
||||
#define QIO_CHANNEL_BUFFER_H
|
||||
|
||||
#include "io/channel.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_QIO_CHANNEL_BUFFER "qio-channel-buffer"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(QIOChannelBuffer, QIO_CHANNEL_BUFFER)
|
||||
|
||||
|
||||
/**
|
||||
* QIOChannelBuffer:
|
||||
*
|
||||
* The QIOChannelBuffer object provides a channel implementation
|
||||
* that is able to perform I/O to/from a memory buffer.
|
||||
*
|
||||
*/
|
||||
|
||||
struct QIOChannelBuffer {
|
||||
QIOChannel parent;
|
||||
size_t capacity; /* Total allocated memory */
|
||||
size_t usage; /* Current size of data */
|
||||
size_t offset; /* Offset for future I/O ops */
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* qio_channel_buffer_new:
|
||||
* @capacity: the initial buffer capacity to allocate
|
||||
*
|
||||
* Allocate a new buffer which is initially empty
|
||||
*
|
||||
* Returns: the new channel object
|
||||
*/
|
||||
QIOChannelBuffer *
|
||||
qio_channel_buffer_new(size_t capacity);
|
||||
|
||||
#endif /* QIO_CHANNEL_BUFFER_H */
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* QEMU I/O channels external command driver
|
||||
*
|
||||
* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QIO_CHANNEL_COMMAND_H
|
||||
#define QIO_CHANNEL_COMMAND_H
|
||||
|
||||
#include "io/channel.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_QIO_CHANNEL_COMMAND "qio-channel-command"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(QIOChannelCommand, QIO_CHANNEL_COMMAND)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* QIOChannelCommand:
|
||||
*
|
||||
* The QIOChannelCommand class provides a channel implementation
|
||||
* that can transport data with an externally running command
|
||||
* via its stdio streams.
|
||||
*/
|
||||
|
||||
struct QIOChannelCommand {
|
||||
QIOChannel parent;
|
||||
int writefd;
|
||||
int readfd;
|
||||
GPid pid;
|
||||
#ifdef WIN32
|
||||
bool blocking;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* qio_channel_command_new_spawn:
|
||||
* @argv: the NULL terminated list of command arguments
|
||||
* @flags: the I/O mode, one of O_RDONLY, O_WRONLY, O_RDWR
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Create a channel for performing I/O with the
|
||||
* command to be spawned with arguments @argv.
|
||||
*
|
||||
* Returns: the command channel object, or NULL on error
|
||||
*/
|
||||
QIOChannelCommand *
|
||||
qio_channel_command_new_spawn(const char *const argv[],
|
||||
int flags,
|
||||
Error **errp);
|
||||
|
||||
|
||||
#endif /* QIO_CHANNEL_COMMAND_H */
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* QEMU I/O channels files driver
|
||||
*
|
||||
* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QIO_CHANNEL_FILE_H
|
||||
#define QIO_CHANNEL_FILE_H
|
||||
|
||||
#include "io/channel.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_QIO_CHANNEL_FILE "qio-channel-file"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(QIOChannelFile, QIO_CHANNEL_FILE)
|
||||
|
||||
|
||||
/**
|
||||
* QIOChannelFile:
|
||||
*
|
||||
* The QIOChannelFile object provides a channel implementation
|
||||
* that is able to perform I/O on block devices, character
|
||||
* devices, FIFOs, pipes and plain files. While it is technically
|
||||
* able to work on sockets too on the UNIX platform, this is not
|
||||
* portable to Windows and lacks some extra sockets specific
|
||||
* functionality. So the QIOChannelSocket object is recommended
|
||||
* for that use case.
|
||||
*
|
||||
*/
|
||||
|
||||
struct QIOChannelFile {
|
||||
QIOChannel parent;
|
||||
int fd;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* qio_channel_file_new_fd:
|
||||
* @fd: the file descriptor
|
||||
*
|
||||
* Create a new IO channel object for a file represented
|
||||
* by the @fd parameter. @fd can be associated with a
|
||||
* block device, character device, fifo, pipe, or a
|
||||
* regular file. For sockets, the QIOChannelSocket class
|
||||
* should be used instead, as this provides greater
|
||||
* functionality and cross platform portability.
|
||||
*
|
||||
* The channel will own the passed in file descriptor
|
||||
* and will take responsibility for closing it, so the
|
||||
* caller must not close it. If appropriate the caller
|
||||
* should dup() its FD before opening the channel.
|
||||
*
|
||||
* Returns: the new channel object
|
||||
*/
|
||||
QIOChannelFile *
|
||||
qio_channel_file_new_fd(int fd);
|
||||
|
||||
/**
|
||||
* qio_channel_file_new_dupfd:
|
||||
* @fd: the file descriptor
|
||||
* @errp: pointer to initialized error object
|
||||
*
|
||||
* Create a new IO channel object for a file represented by the @fd
|
||||
* parameter. Like qio_channel_file_new_fd(), but the @fd is first
|
||||
* duplicated with dup().
|
||||
*
|
||||
* The channel will own the duplicated file descriptor and will take
|
||||
* responsibility for closing it, the original FD is owned by the
|
||||
* caller.
|
||||
*
|
||||
* Returns: the new channel object
|
||||
*/
|
||||
QIOChannelFile *
|
||||
qio_channel_file_new_dupfd(int fd, Error **errp);
|
||||
|
||||
/**
|
||||
* qio_channel_file_new_path:
|
||||
* @path: the file path
|
||||
* @flags: the open flags (O_RDONLY|O_WRONLY|O_RDWR, etc)
|
||||
* @mode: the file creation mode if O_CREAT is set in @flags
|
||||
* @errp: pointer to initialized error object
|
||||
*
|
||||
* Create a new IO channel object for a file represented
|
||||
* by the @path parameter. @path can point to any
|
||||
* type of file on which sequential I/O can be
|
||||
* performed, whether it be a plain file, character
|
||||
* device or block device.
|
||||
*
|
||||
* Returns: the new channel object
|
||||
*/
|
||||
QIOChannelFile *
|
||||
qio_channel_file_new_path(const char *path,
|
||||
int flags,
|
||||
mode_t mode,
|
||||
Error **errp);
|
||||
|
||||
#endif /* QIO_CHANNEL_FILE_H */
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* QEMU I/O channels null driver
|
||||
*
|
||||
* Copyright (c) 2022 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QIO_CHANNEL_FILE_H
|
||||
#define QIO_CHANNEL_FILE_H
|
||||
|
||||
#include "io/channel.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_QIO_CHANNEL_NULL "qio-channel-null"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(QIOChannelNull, QIO_CHANNEL_NULL)
|
||||
|
||||
|
||||
/**
|
||||
* QIOChannelNull:
|
||||
*
|
||||
* The QIOChannelNull object provides a channel implementation
|
||||
* that discards all writes and returns EOF for all reads.
|
||||
*/
|
||||
|
||||
struct QIOChannelNull {
|
||||
QIOChannel parent;
|
||||
bool closed;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* qio_channel_null_new:
|
||||
*
|
||||
* Create a new IO channel object that discards all writes
|
||||
* and returns EOF for all reads.
|
||||
*
|
||||
* Returns: the new channel object
|
||||
*/
|
||||
QIOChannelNull *
|
||||
qio_channel_null_new(void);
|
||||
|
||||
#endif /* QIO_CHANNEL_NULL_H */
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* QEMU I/O channels sockets driver
|
||||
*
|
||||
* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QIO_CHANNEL_SOCKET_H
|
||||
#define QIO_CHANNEL_SOCKET_H
|
||||
|
||||
#include "io/channel.h"
|
||||
#include "io/task.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_QIO_CHANNEL_SOCKET "qio-channel-socket"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(QIOChannelSocket, QIO_CHANNEL_SOCKET)
|
||||
|
||||
|
||||
/**
|
||||
* QIOChannelSocket:
|
||||
*
|
||||
* The QIOChannelSocket class provides a channel implementation
|
||||
* that can transport data over a UNIX socket or TCP socket.
|
||||
* Beyond the core channel API, it also provides functionality
|
||||
* for accepting client connections, tuning some socket
|
||||
* parameters and getting socket address strings.
|
||||
*/
|
||||
|
||||
struct QIOChannelSocket {
|
||||
QIOChannel parent;
|
||||
int fd;
|
||||
struct sockaddr_storage localAddr;
|
||||
socklen_t localAddrLen;
|
||||
struct sockaddr_storage remoteAddr;
|
||||
socklen_t remoteAddrLen;
|
||||
ssize_t zero_copy_queued;
|
||||
ssize_t zero_copy_sent;
|
||||
bool blocking;
|
||||
bool zero_copy_fallback;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* qio_channel_socket_new:
|
||||
*
|
||||
* Create a channel for performing I/O on a socket
|
||||
* connection, that is initially closed. After
|
||||
* creating the socket, it must be setup as a client
|
||||
* connection or server.
|
||||
*
|
||||
* Returns: the socket channel object
|
||||
*/
|
||||
QIOChannelSocket *
|
||||
qio_channel_socket_new(void);
|
||||
|
||||
/**
|
||||
* qio_channel_socket_new_fd:
|
||||
* @fd: the socket file descriptor
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Create a channel for performing I/O on the socket
|
||||
* connection represented by the file descriptor @fd.
|
||||
*
|
||||
* Returns: the socket channel object, or NULL on error
|
||||
*/
|
||||
QIOChannelSocket *
|
||||
qio_channel_socket_new_fd(int fd,
|
||||
Error **errp);
|
||||
|
||||
|
||||
/**
|
||||
* qio_channel_socket_connect_sync:
|
||||
* @ioc: the socket channel object
|
||||
* @addr: the address to connect to
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Attempt to connect to the address @addr. This method
|
||||
* will run in the foreground so the caller will not regain
|
||||
* execution control until the connection is established or
|
||||
* an error occurs.
|
||||
*/
|
||||
int qio_channel_socket_connect_sync(QIOChannelSocket *ioc,
|
||||
SocketAddress *addr,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* qio_channel_socket_connect_async:
|
||||
* @ioc: the socket channel object
|
||||
* @addr: the address to connect to
|
||||
* @callback: the function to invoke on completion
|
||||
* @opaque: user data to pass to @callback
|
||||
* @destroy: the function to free @opaque
|
||||
* @context: the context to run the async task. If %NULL, the default
|
||||
* context will be used.
|
||||
*
|
||||
* Attempt to connect to the address @addr. This method
|
||||
* will run in the background so the caller will regain
|
||||
* execution control immediately. The function @callback
|
||||
* will be invoked on completion or failure. The @addr
|
||||
* parameter will be copied, so may be freed as soon
|
||||
* as this function returns without waiting for completion.
|
||||
*/
|
||||
void qio_channel_socket_connect_async(QIOChannelSocket *ioc,
|
||||
SocketAddress *addr,
|
||||
QIOTaskFunc callback,
|
||||
gpointer opaque,
|
||||
GDestroyNotify destroy,
|
||||
GMainContext *context);
|
||||
|
||||
|
||||
/**
|
||||
* qio_channel_socket_listen_sync:
|
||||
* @ioc: the socket channel object
|
||||
* @addr: the address to listen to
|
||||
* @num: the expected amount of connections
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Attempt to listen to the address @addr. This method
|
||||
* will run in the foreground so the caller will not regain
|
||||
* execution control until the connection is established or
|
||||
* an error occurs.
|
||||
*/
|
||||
int qio_channel_socket_listen_sync(QIOChannelSocket *ioc,
|
||||
SocketAddress *addr,
|
||||
int num,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* qio_channel_socket_listen_async:
|
||||
* @ioc: the socket channel object
|
||||
* @addr: the address to listen to
|
||||
* @num: the expected amount of connections
|
||||
* @callback: the function to invoke on completion
|
||||
* @opaque: user data to pass to @callback
|
||||
* @destroy: the function to free @opaque
|
||||
* @context: the context to run the async task. If %NULL, the default
|
||||
* context will be used.
|
||||
*
|
||||
* Attempt to listen to the address @addr. This method
|
||||
* will run in the background so the caller will regain
|
||||
* execution control immediately. The function @callback
|
||||
* will be invoked on completion or failure. The @addr
|
||||
* parameter will be copied, so may be freed as soon
|
||||
* as this function returns without waiting for completion.
|
||||
*/
|
||||
void qio_channel_socket_listen_async(QIOChannelSocket *ioc,
|
||||
SocketAddress *addr,
|
||||
int num,
|
||||
QIOTaskFunc callback,
|
||||
gpointer opaque,
|
||||
GDestroyNotify destroy,
|
||||
GMainContext *context);
|
||||
|
||||
|
||||
/**
|
||||
* qio_channel_socket_dgram_sync:
|
||||
* @ioc: the socket channel object
|
||||
* @localAddr: the address to local bind address
|
||||
* @remoteAddr: the address to remote peer address
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Attempt to initialize a datagram socket bound to
|
||||
* @localAddr and communicating with peer @remoteAddr.
|
||||
* This method will run in the foreground so the caller
|
||||
* will not regain execution control until the socket
|
||||
* is established or an error occurs.
|
||||
*/
|
||||
int qio_channel_socket_dgram_sync(QIOChannelSocket *ioc,
|
||||
SocketAddress *localAddr,
|
||||
SocketAddress *remoteAddr,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* qio_channel_socket_dgram_async:
|
||||
* @ioc: the socket channel object
|
||||
* @localAddr: the address to local bind address
|
||||
* @remoteAddr: the address to remote peer address
|
||||
* @callback: the function to invoke on completion
|
||||
* @opaque: user data to pass to @callback
|
||||
* @destroy: the function to free @opaque
|
||||
* @context: the context to run the async task. If %NULL, the default
|
||||
* context will be used.
|
||||
*
|
||||
* Attempt to initialize a datagram socket bound to
|
||||
* @localAddr and communicating with peer @remoteAddr.
|
||||
* This method will run in the background so the caller
|
||||
* will regain execution control immediately. The function
|
||||
* @callback will be invoked on completion or failure.
|
||||
* The @localAddr and @remoteAddr parameters will be copied,
|
||||
* so may be freed as soon as this function returns without
|
||||
* waiting for completion.
|
||||
*/
|
||||
void qio_channel_socket_dgram_async(QIOChannelSocket *ioc,
|
||||
SocketAddress *localAddr,
|
||||
SocketAddress *remoteAddr,
|
||||
QIOTaskFunc callback,
|
||||
gpointer opaque,
|
||||
GDestroyNotify destroy,
|
||||
GMainContext *context);
|
||||
|
||||
|
||||
/**
|
||||
* qio_channel_socket_get_local_address:
|
||||
* @ioc: the socket channel object
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Get the string representation of the local socket
|
||||
* address. A pointer to the allocated address information
|
||||
* struct will be returned, which the caller is required to
|
||||
* release with a call qapi_free_SocketAddress() when no
|
||||
* longer required.
|
||||
*
|
||||
* Returns: the socket address struct, or NULL on error
|
||||
*/
|
||||
SocketAddress *
|
||||
qio_channel_socket_get_local_address(QIOChannelSocket *ioc,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* qio_channel_socket_get_remote_address:
|
||||
* @ioc: the socket channel object
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Get the string representation of the local socket
|
||||
* address. A pointer to the allocated address information
|
||||
* struct will be returned, which the caller is required to
|
||||
* release with a call qapi_free_SocketAddress() when no
|
||||
* longer required.
|
||||
*
|
||||
* Returns: the socket address struct, or NULL on error
|
||||
*/
|
||||
SocketAddress *
|
||||
qio_channel_socket_get_remote_address(QIOChannelSocket *ioc,
|
||||
Error **errp);
|
||||
|
||||
|
||||
/**
|
||||
* qio_channel_socket_accept:
|
||||
* @ioc: the socket channel object
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* If the socket represents a server, then this accepts
|
||||
* a new client connection. The returned channel will
|
||||
* represent the connected client socket.
|
||||
*
|
||||
* Returns: the new client channel, or NULL on error
|
||||
*/
|
||||
QIOChannelSocket *
|
||||
qio_channel_socket_accept(QIOChannelSocket *ioc,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* qio_channel_socket_set_send_buffer:
|
||||
* @ioc: the socket channel object
|
||||
* @size: buffer size
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Set the underlying socket send buffer size.
|
||||
*
|
||||
* Retruns: 0 on success, or -1 on error.
|
||||
*/
|
||||
int qio_channel_socket_set_send_buffer(QIOChannelSocket *ioc,
|
||||
size_t size,
|
||||
Error **errp);
|
||||
|
||||
#endif /* QIO_CHANNEL_SOCKET_H */
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* QEMU I/O channels TLS driver
|
||||
*
|
||||
* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QIO_CHANNEL_TLS_H
|
||||
#define QIO_CHANNEL_TLS_H
|
||||
|
||||
#include "io/channel.h"
|
||||
#include "io/task.h"
|
||||
#include "crypto/tlssession.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_QIO_CHANNEL_TLS "qio-channel-tls"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(QIOChannelTLS, QIO_CHANNEL_TLS)
|
||||
|
||||
|
||||
/**
|
||||
* QIOChannelTLS
|
||||
*
|
||||
* The QIOChannelTLS class provides a channel wrapper which
|
||||
* can transparently run the TLS encryption protocol. It is
|
||||
* usually used over a TCP socket, but there is actually no
|
||||
* technical restriction on which type of master channel is
|
||||
* used as the transport.
|
||||
*
|
||||
* This channel object is capable of running as either a
|
||||
* TLS server or TLS client.
|
||||
*/
|
||||
|
||||
struct QIOChannelTLS {
|
||||
QIOChannel parent;
|
||||
QIOChannel *master;
|
||||
QCryptoTLSSession *session;
|
||||
QIOChannelShutdown shutdown;
|
||||
guint hs_ioc_tag;
|
||||
guint bye_ioc_tag;
|
||||
};
|
||||
|
||||
/**
|
||||
* qio_channel_tls_bye:
|
||||
* @ioc: the TLS channel object
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Perform the TLS session termination. This method will return
|
||||
* immediately and the termination will continue in the background,
|
||||
* provided the main loop is running.
|
||||
*/
|
||||
void qio_channel_tls_bye(QIOChannelTLS *ioc, Error **errp);
|
||||
|
||||
/**
|
||||
* qio_channel_tls_new_server:
|
||||
* @master: the underlying channel object
|
||||
* @creds: the credentials to use for TLS handshake
|
||||
* @aclname: the access control list for validating clients
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Create a new TLS channel that runs the server side of
|
||||
* a TLS session. The TLS session handshake will use the
|
||||
* credentials provided in @creds. If the @aclname parameter
|
||||
* is non-NULL, then the client will have to provide
|
||||
* credentials (ie a x509 client certificate) which will
|
||||
* then be validated against the ACL.
|
||||
*
|
||||
* After creating the channel, it is mandatory to call
|
||||
* the qio_channel_tls_handshake() method before attempting
|
||||
* todo any I/O on the channel.
|
||||
*
|
||||
* Once the handshake has completed, all I/O should be done
|
||||
* via the new TLS channel object and not the original
|
||||
* master channel
|
||||
*
|
||||
* Returns: the new TLS channel object, or NULL
|
||||
*/
|
||||
QIOChannelTLS *
|
||||
qio_channel_tls_new_server(QIOChannel *master,
|
||||
QCryptoTLSCreds *creds,
|
||||
const char *aclname,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* qio_channel_tls_new_client:
|
||||
* @master: the underlying channel object
|
||||
* @creds: the credentials to use for TLS handshake
|
||||
* @hostname: the user specified server hostname
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Create a new TLS channel that runs the client side of
|
||||
* a TLS session. The TLS session handshake will use the
|
||||
* credentials provided in @creds. The @hostname parameter
|
||||
* should provide the user specified hostname of the server
|
||||
* and will be validated against the server's credentials
|
||||
* (ie CommonName of the x509 certificate)
|
||||
*
|
||||
* After creating the channel, it is mandatory to call
|
||||
* the qio_channel_tls_handshake() method before attempting
|
||||
* todo any I/O on the channel.
|
||||
*
|
||||
* Once the handshake has completed, all I/O should be done
|
||||
* via the new TLS channel object and not the original
|
||||
* master channel
|
||||
*
|
||||
* Returns: the new TLS channel object, or NULL
|
||||
*/
|
||||
QIOChannelTLS *
|
||||
qio_channel_tls_new_client(QIOChannel *master,
|
||||
QCryptoTLSCreds *creds,
|
||||
const char *hostname,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* qio_channel_tls_handshake:
|
||||
* @ioc: the TLS channel object
|
||||
* @func: the callback to invoke when completed
|
||||
* @opaque: opaque data to pass to @func
|
||||
* @destroy: optional callback to free @opaque
|
||||
* @context: the context that TLS handshake will run with. If %NULL,
|
||||
* the default context will be used
|
||||
*
|
||||
* Perform the TLS session handshake. This method
|
||||
* will return immediately and the handshake will
|
||||
* continue in the background, provided the main
|
||||
* loop is running. When the handshake is complete,
|
||||
* or fails, the @func callback will be invoked.
|
||||
*/
|
||||
void qio_channel_tls_handshake(QIOChannelTLS *ioc,
|
||||
QIOTaskFunc func,
|
||||
gpointer opaque,
|
||||
GDestroyNotify destroy,
|
||||
GMainContext *context);
|
||||
|
||||
/**
|
||||
* qio_channel_tls_get_session:
|
||||
* @ioc: the TLS channel object
|
||||
*
|
||||
* Get the TLS session used by the channel.
|
||||
*
|
||||
* Returns: the TLS session
|
||||
*/
|
||||
QCryptoTLSSession *
|
||||
qio_channel_tls_get_session(QIOChannelTLS *ioc);
|
||||
|
||||
#endif /* QIO_CHANNEL_TLS_H */
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* QEMU I/O channels utility APIs
|
||||
*
|
||||
* Copyright (c) 2016 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QIO_CHANNEL_UTIL_H
|
||||
#define QIO_CHANNEL_UTIL_H
|
||||
|
||||
#include "io/channel.h"
|
||||
|
||||
/*
|
||||
* This module provides helper functions that are useful when dealing
|
||||
* with QIOChannel objects
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* qio_channel_new_fd:
|
||||
* @fd: the file descriptor
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Create a channel for performing I/O on the file
|
||||
* descriptor @fd. The particular subclass of QIOChannel
|
||||
* that is returned will depend on what underlying object
|
||||
* the file descriptor is associated with. It may be either
|
||||
* a QIOChannelSocket or a QIOChannelFile instance. Upon
|
||||
* success, the returned QIOChannel instance will own
|
||||
* the @fd file descriptor, and take responsibility for
|
||||
* closing it when no longer required. On failure, the
|
||||
* caller is responsible for closing @fd.
|
||||
*
|
||||
* Returns: the channel object, or NULL on error
|
||||
*/
|
||||
QIOChannel *qio_channel_new_fd(int fd,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* qio_channel_util_set_aio_fd_handler:
|
||||
* @read_fd: the file descriptor for the read handler
|
||||
* @read_ctx: the AioContext for the read handler
|
||||
* @io_read: the read handler
|
||||
* @write_fd: the file descriptor for the write handler
|
||||
* @write_ctx: the AioContext for the write handler
|
||||
* @io_write: the write handler
|
||||
* @opaque: the opaque argument to the read and write handler
|
||||
*
|
||||
* Set the read and write handlers when @read_ctx and @write_ctx are non-NULL,
|
||||
* respectively. To leave a handler in its current state, pass a NULL
|
||||
* AioContext. To clear a handler, pass a non-NULL AioContext and a NULL
|
||||
* handler.
|
||||
*/
|
||||
void qio_channel_util_set_aio_fd_handler(int read_fd,
|
||||
AioContext *read_ctx,
|
||||
IOHandler *io_read,
|
||||
int write_fd,
|
||||
AioContext *write_ctx,
|
||||
IOHandler *io_write,
|
||||
void *opaque);
|
||||
|
||||
#endif /* QIO_CHANNEL_UTIL_H */
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* QEMU I/O channels watch helper APIs
|
||||
*
|
||||
* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QIO_CHANNEL_WATCH_H
|
||||
#define QIO_CHANNEL_WATCH_H
|
||||
|
||||
#include "io/channel.h"
|
||||
|
||||
/*
|
||||
* This module provides helper functions that will be needed by
|
||||
* the various QIOChannel implementations, for creating watches
|
||||
* on file descriptors / sockets
|
||||
*/
|
||||
|
||||
/**
|
||||
* qio_channel_create_fd_watch:
|
||||
* @ioc: the channel object
|
||||
* @fd: the file descriptor
|
||||
* @condition: the I/O condition
|
||||
*
|
||||
* Create a new main loop source that is able to
|
||||
* monitor the file descriptor @fd for the
|
||||
* I/O conditions in @condition. This is able
|
||||
* monitor block devices, character devices,
|
||||
* pipes but not plain files or, on Win32, sockets.
|
||||
*
|
||||
* Returns: the new main loop source
|
||||
*/
|
||||
GSource *qio_channel_create_fd_watch(QIOChannel *ioc,
|
||||
int fd,
|
||||
GIOCondition condition);
|
||||
|
||||
/**
|
||||
* qio_channel_create_socket_watch:
|
||||
* @ioc: the channel object
|
||||
* @fd: the file descriptor
|
||||
* @condition: the I/O condition
|
||||
*
|
||||
* Create a new main loop source that is able to
|
||||
* monitor the file descriptor @fd for the
|
||||
* I/O conditions in @condition. This is equivalent
|
||||
* to qio_channel_create_fd_watch on POSIX systems
|
||||
* but not on Windows.
|
||||
*
|
||||
* Returns: the new main loop source
|
||||
*/
|
||||
GSource *qio_channel_create_socket_watch(QIOChannel *ioc,
|
||||
int fd,
|
||||
GIOCondition condition);
|
||||
|
||||
/**
|
||||
* qio_channel_create_fd_pair_watch:
|
||||
* @ioc: the channel object
|
||||
* @fdread: the file descriptor for reading
|
||||
* @fdwrite: the file descriptor for writing
|
||||
* @condition: the I/O condition
|
||||
*
|
||||
* Create a new main loop source that is able to
|
||||
* monitor the pair of file descriptors @fdread
|
||||
* and @fdwrite for the I/O conditions in @condition.
|
||||
* This is intended for monitoring unidirectional
|
||||
* file descriptors such as pipes, where a pair
|
||||
* of descriptors is required for bidirectional
|
||||
* I/O
|
||||
*
|
||||
* Returns: the new main loop source
|
||||
*/
|
||||
GSource *qio_channel_create_fd_pair_watch(QIOChannel *ioc,
|
||||
int fdread,
|
||||
int fdwrite,
|
||||
GIOCondition condition);
|
||||
|
||||
#endif /* QIO_CHANNEL_WATCH_H */
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* QEMU I/O channels driver websockets
|
||||
*
|
||||
* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QIO_CHANNEL_WEBSOCK_H
|
||||
#define QIO_CHANNEL_WEBSOCK_H
|
||||
|
||||
#include "io/channel.h"
|
||||
#include "qemu/buffer.h"
|
||||
#include "io/task.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_QIO_CHANNEL_WEBSOCK "qio-channel-websock"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(QIOChannelWebsock, QIO_CHANNEL_WEBSOCK)
|
||||
|
||||
typedef union QIOChannelWebsockMask QIOChannelWebsockMask;
|
||||
|
||||
union QIOChannelWebsockMask {
|
||||
char c[4];
|
||||
uint32_t u;
|
||||
};
|
||||
|
||||
/**
|
||||
* QIOChannelWebsock
|
||||
*
|
||||
* The QIOChannelWebsock class provides a channel wrapper which
|
||||
* can transparently run the HTTP websockets protocol. This is
|
||||
* usually used over a TCP socket, but there is actually no
|
||||
* technical restriction on which type of master channel is
|
||||
* used as the transport.
|
||||
*
|
||||
* This channel object is currently only capable of running as
|
||||
* a websocket server and is a pretty crude implementation
|
||||
* of it, not supporting the full websockets protocol feature
|
||||
* set. It is sufficient to use with a simple websockets
|
||||
* client for encapsulating VNC for noVNC in-browser client.
|
||||
*/
|
||||
|
||||
struct QIOChannelWebsock {
|
||||
QIOChannel parent;
|
||||
QIOChannel *master;
|
||||
Buffer encinput;
|
||||
Buffer encoutput;
|
||||
Buffer rawinput;
|
||||
size_t payload_remain;
|
||||
size_t pong_remain;
|
||||
QIOChannelWebsockMask mask;
|
||||
guint hs_io_tag; /* tracking handshake task */
|
||||
guint io_tag; /* tracking watch task */
|
||||
Error *io_err;
|
||||
gboolean io_eof;
|
||||
uint8_t opcode;
|
||||
};
|
||||
|
||||
/**
|
||||
* qio_channel_websock_new_server:
|
||||
* @master: the underlying channel object
|
||||
*
|
||||
* Create a new websockets channel that runs the server
|
||||
* side of the protocol.
|
||||
*
|
||||
* After creating the channel, it is mandatory to call
|
||||
* the qio_channel_websock_handshake() method before attempting
|
||||
* todo any I/O on the channel.
|
||||
*
|
||||
* Once the handshake has completed, all I/O should be done
|
||||
* via the new websocket channel object and not the original
|
||||
* master channel
|
||||
*
|
||||
* Returns: the new websockets channel object
|
||||
*/
|
||||
QIOChannelWebsock *
|
||||
qio_channel_websock_new_server(QIOChannel *master);
|
||||
|
||||
/**
|
||||
* qio_channel_websock_handshake:
|
||||
* @ioc: the websocket channel object
|
||||
* @func: the callback to invoke when completed
|
||||
* @opaque: opaque data to pass to @func
|
||||
* @destroy: optional callback to free @opaque
|
||||
*
|
||||
* Perform the websocket handshake. This method
|
||||
* will return immediately and the handshake will
|
||||
* continue in the background, provided the main
|
||||
* loop is running. When the handshake is complete,
|
||||
* or fails, the @func callback will be invoked.
|
||||
*/
|
||||
void qio_channel_websock_handshake(QIOChannelWebsock *ioc,
|
||||
QIOTaskFunc func,
|
||||
gpointer opaque,
|
||||
GDestroyNotify destroy);
|
||||
|
||||
#endif /* QIO_CHANNEL_WEBSOCK_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* QEMU DNS resolver
|
||||
*
|
||||
* Copyright (c) 2016-2017 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QIO_DNS_RESOLVER_H
|
||||
#define QIO_DNS_RESOLVER_H
|
||||
|
||||
#include "qapi/qapi-types-sockets.h"
|
||||
#include "qom/object.h"
|
||||
#include "io/task.h"
|
||||
|
||||
#define TYPE_QIO_DNS_RESOLVER "qio-dns-resolver"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(QIODNSResolver,
|
||||
QIO_DNS_RESOLVER)
|
||||
|
||||
|
||||
/**
|
||||
* QIODNSResolver:
|
||||
*
|
||||
* The QIODNSResolver class provides a framework for doing
|
||||
* DNS resolution on SocketAddress objects, independently
|
||||
* of socket creation.
|
||||
*
|
||||
* <example>
|
||||
* <title>Resolving addresses synchronously</title>
|
||||
* <programlisting>
|
||||
* int mylisten(SocketAddress *addr, Error **errp) {
|
||||
* QIODNSResolver *resolver = qio_dns_resolver_get_instance();
|
||||
* SocketAddress **rawaddrs = NULL;
|
||||
* size_t nrawaddrs = 0;
|
||||
* Error *err = NULL;
|
||||
* QIOChannel **socks = NULL;
|
||||
* size_t nsocks = 0;
|
||||
*
|
||||
* if (qio_dns_resolver_lookup_sync(dns, addr, &nrawaddrs,
|
||||
* &rawaddrs, errp) < 0) {
|
||||
* return -1;
|
||||
* }
|
||||
*
|
||||
* for (i = 0; i < nrawaddrs; i++) {
|
||||
* QIOChannel *sock = qio_channel_new();
|
||||
* Error *local_err = NULL;
|
||||
* qio_channel_listen_sync(sock, rawaddrs[i], &local_err);
|
||||
* if (local_err) {
|
||||
* error_propagate(&err, local_err);
|
||||
* } else {
|
||||
* socks = g_renew(QIOChannelSocket *, socks, nsocks + 1);
|
||||
* socks[nsocks++] = sock;
|
||||
* }
|
||||
* qapi_free_SocketAddress(rawaddrs[i]);
|
||||
* }
|
||||
* g_free(rawaddrs);
|
||||
*
|
||||
* if (nsocks == 0) {
|
||||
* error_propagate(errp, err);
|
||||
* } else {
|
||||
* error_free(err);
|
||||
* }
|
||||
* }
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
* <example>
|
||||
* <title>Resolving addresses asynchronously</title>
|
||||
* <programlisting>
|
||||
* typedef struct MyListenData {
|
||||
* Error *err;
|
||||
* QIOChannelSocket **socks;
|
||||
* size_t nsocks;
|
||||
* } MyListenData;
|
||||
*
|
||||
* void mylistenresult(QIOTask *task, void *opaque) {
|
||||
* MyListenData *data = opaque;
|
||||
* QIODNSResolver *resolver =
|
||||
* QIO_DNS_RESOLVER(qio_task_get_source(task);
|
||||
* SocketAddress **rawaddrs = NULL;
|
||||
* size_t nrawaddrs = 0;
|
||||
* Error *err = NULL;
|
||||
*
|
||||
* if (qio_task_propagate_error(task, &data->err)) {
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* qio_dns_resolver_lookup_result(resolver, task,
|
||||
* &nrawaddrs, &rawaddrs);
|
||||
*
|
||||
* for (i = 0; i < nrawaddrs; i++) {
|
||||
* QIOChannel *sock = qio_channel_new();
|
||||
* Error *local_err = NULL;
|
||||
* qio_channel_listen_sync(sock, rawaddrs[i], &local_err);
|
||||
* if (local_err) {
|
||||
* error_propagate(&err, local_err);
|
||||
* } else {
|
||||
* socks = g_renew(QIOChannelSocket *, socks, nsocks + 1);
|
||||
* socks[nsocks++] = sock;
|
||||
* }
|
||||
* qapi_free_SocketAddress(rawaddrs[i]);
|
||||
* }
|
||||
* g_free(rawaddrs);
|
||||
*
|
||||
* if (nsocks == 0) {
|
||||
* error_propagate(&data->err, err);
|
||||
* } else {
|
||||
* error_free(err);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* void mylisten(SocketAddress *addr, MyListenData *data) {
|
||||
* QIODNSResolver *resolver = qio_dns_resolver_get_instance();
|
||||
* qio_dns_resolver_lookup_async(dns, addr,
|
||||
* mylistenresult, data, NULL);
|
||||
* }
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*/
|
||||
struct QIODNSResolver {
|
||||
Object parent;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* qio_dns_resolver_get_instance:
|
||||
*
|
||||
* Get the singleton dns resolver instance. The caller
|
||||
* does not own a reference on the returned object.
|
||||
*
|
||||
* Returns: the single dns resolver instance
|
||||
*/
|
||||
QIODNSResolver *qio_dns_resolver_get_instance(void);
|
||||
|
||||
/**
|
||||
* qio_dns_resolver_lookup_sync:
|
||||
* @resolver: the DNS resolver instance
|
||||
* @addr: the address to resolve
|
||||
* @naddr: pointer to hold number of resolved addresses
|
||||
* @addrs: pointer to hold resolved addresses
|
||||
* @errp: pointer to NULL initialized error object
|
||||
*
|
||||
* This will attempt to resolve the address provided
|
||||
* in @addr. If resolution succeeds, @addrs will be filled
|
||||
* with all the resolved addresses. @naddrs will specify
|
||||
* the number of entries allocated in @addrs. The caller
|
||||
* is responsible for freeing each entry in @addrs, as
|
||||
* well as @addrs itself. @naddrs is guaranteed to be
|
||||
* greater than zero on success.
|
||||
*
|
||||
* DNS resolution will be done synchronously so execution
|
||||
* of the caller may be blocked for an arbitrary length
|
||||
* of time.
|
||||
*
|
||||
* Returns: 0 if resolution was successful, -1 on error
|
||||
*/
|
||||
int qio_dns_resolver_lookup_sync(QIODNSResolver *resolver,
|
||||
SocketAddress *addr,
|
||||
size_t *naddrs,
|
||||
SocketAddress ***addrs,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* qio_dns_resolver_lookup_async:
|
||||
* @resolver: the DNS resolver instance
|
||||
* @addr: the address to resolve
|
||||
* @func: the callback to invoke on lookup completion
|
||||
* @opaque: data blob to pass to @func
|
||||
* @notify: the callback to free @opaque, or NULL
|
||||
*
|
||||
* This will attempt to resolve the address provided
|
||||
* in @addr. The callback @func will be invoked when
|
||||
* resolution has either completed or failed. On
|
||||
* success, the @func should call the method
|
||||
* qio_dns_resolver_lookup_result() to obtain the
|
||||
* results.
|
||||
*
|
||||
* DNS resolution will be done asynchronously so execution
|
||||
* of the caller will not be blocked.
|
||||
*/
|
||||
void qio_dns_resolver_lookup_async(QIODNSResolver *resolver,
|
||||
SocketAddress *addr,
|
||||
QIOTaskFunc func,
|
||||
gpointer opaque,
|
||||
GDestroyNotify notify);
|
||||
|
||||
/**
|
||||
* qio_dns_resolver_lookup_result:
|
||||
* @resolver: the DNS resolver instance
|
||||
* @task: the task object to get results for
|
||||
* @naddr: pointer to hold number of resolved addresses
|
||||
* @addrs: pointer to hold resolved addresses
|
||||
*
|
||||
* This method should be called from the callback passed
|
||||
* to qio_dns_resolver_lookup_async() in order to obtain
|
||||
* results. @addrs will be filled with all the resolved
|
||||
* addresses. @naddrs will specify the number of entries
|
||||
* allocated in @addrs. The caller is responsible for
|
||||
* freeing each entry in @addrs, as well as @addrs itself.
|
||||
*/
|
||||
void qio_dns_resolver_lookup_result(QIODNSResolver *resolver,
|
||||
QIOTask *task,
|
||||
size_t *naddrs,
|
||||
SocketAddress ***addrs);
|
||||
|
||||
#endif /* QIO_DNS_RESOLVER_H */
|
||||
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* QEMU network listener
|
||||
*
|
||||
* Copyright (c) 2016-2017 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QIO_NET_LISTENER_H
|
||||
#define QIO_NET_LISTENER_H
|
||||
|
||||
#include "io/channel-socket.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_QIO_NET_LISTENER "qio-net-listener"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(QIONetListener,
|
||||
QIO_NET_LISTENER)
|
||||
|
||||
typedef struct QIONetListenerSource QIONetListenerSource;
|
||||
|
||||
typedef void (*QIONetListenerClientFunc)(QIONetListener *listener,
|
||||
QIOChannelSocket *sioc,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* QIONetListener:
|
||||
*
|
||||
* The QIONetListener object encapsulates the management of a
|
||||
* listening socket. It is able to listen on multiple sockets
|
||||
* concurrently, to deal with the scenario where IPv4 / IPv6
|
||||
* needs separate sockets, or there is a need to listen on a
|
||||
* subset of interface IP addresses, instead of the wildcard
|
||||
* address.
|
||||
*/
|
||||
struct QIONetListener {
|
||||
Object parent;
|
||||
|
||||
char *name;
|
||||
QIONetListenerSource **source;
|
||||
size_t nsioc;
|
||||
/* At most one of context or aio_context will be set */
|
||||
GMainContext *context;
|
||||
AioContext *aio_context;
|
||||
|
||||
bool connected;
|
||||
|
||||
QemuMutex lock; /* Protects remaining fields */
|
||||
QIONetListenerClientFunc io_func;
|
||||
gpointer io_data;
|
||||
GDestroyNotify io_notify;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* qio_net_listener_new:
|
||||
*
|
||||
* Create a new network listener service, which is not
|
||||
* listening on any sockets initially.
|
||||
*
|
||||
* Returns: the new listener
|
||||
*/
|
||||
QIONetListener *qio_net_listener_new(void);
|
||||
|
||||
|
||||
/**
|
||||
* qio_net_listener_set_name:
|
||||
* @listener: the network listener object
|
||||
* @name: the listener name
|
||||
*
|
||||
* Set the name of the listener. This is used as a debugging
|
||||
* aid, to set names on any GSource instances associated
|
||||
* with the listener
|
||||
*/
|
||||
void qio_net_listener_set_name(QIONetListener *listener,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* qio_net_listener_open_sync:
|
||||
* @listener: the network listener object
|
||||
* @addr: the address to listen on
|
||||
* @num: the amount of expected connections
|
||||
* @errp: pointer to a NULL initialized error object
|
||||
*
|
||||
* Synchronously open a listening connection on all
|
||||
* addresses associated with @addr. This method may
|
||||
* also be invoked multiple times, in order to have a
|
||||
* single listener on multiple distinct addresses.
|
||||
*/
|
||||
int qio_net_listener_open_sync(QIONetListener *listener,
|
||||
SocketAddress *addr,
|
||||
int num,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* qio_net_listener_add:
|
||||
* @listener: the network listener object
|
||||
* @sioc: the socket I/O channel
|
||||
*
|
||||
* Associate a listening socket I/O channel with the
|
||||
* listener. The listener will acquire a new reference
|
||||
* on @sioc, so the caller should release its own reference
|
||||
* if it no longer requires the object.
|
||||
*/
|
||||
void qio_net_listener_add(QIONetListener *listener,
|
||||
QIOChannelSocket *sioc);
|
||||
|
||||
/**
|
||||
* qio_net_listener_set_client_func_full:
|
||||
* @listener: the network listener object
|
||||
* @func: the callback function
|
||||
* @data: opaque data to pass to @func
|
||||
* @notify: callback to free @data
|
||||
* @context: the context that the sources will be bound to. If %NULL,
|
||||
* the default context will be used.
|
||||
*
|
||||
* Register @func to be invoked whenever a new client
|
||||
* connects to the listener. @func will be invoked
|
||||
* passing in the QIOChannelSocket instance for the
|
||||
* client.
|
||||
*/
|
||||
void qio_net_listener_set_client_func_full(QIONetListener *listener,
|
||||
QIONetListenerClientFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify,
|
||||
GMainContext *context);
|
||||
|
||||
/**
|
||||
* qio_net_listener_set_client_func:
|
||||
* @listener: the network listener object
|
||||
* @func: the callback function
|
||||
* @data: opaque data to pass to @func
|
||||
* @notify: callback to free @data
|
||||
*
|
||||
* Wrapper of qio_net_listener_set_client_func_full(), only that the
|
||||
* sources will always be bound to default main context.
|
||||
*/
|
||||
void qio_net_listener_set_client_func(QIONetListener *listener,
|
||||
QIONetListenerClientFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
|
||||
/**
|
||||
* qio_net_listener_set_client_aio_func:
|
||||
* @listener: the network listener object
|
||||
* @func: the callback function
|
||||
* @data: opaque data to pass to @func
|
||||
* @context: AioContext that @func will be bound to; if NULL, this will
|
||||
* will use qemu_get_aio_context().
|
||||
*
|
||||
* Similar to qio_net_listener_set_client_func_full(), except that the polling
|
||||
* will be done by an AioContext rather than a GMainContext.
|
||||
*
|
||||
* Because AioContext does not (yet) support a clean way to deregister
|
||||
* a callback from one thread while another thread might be in that
|
||||
* callback, this function is only safe to call from the thread
|
||||
* currently associated with @context.
|
||||
*/
|
||||
void qio_net_listener_set_client_aio_func(QIONetListener *listener,
|
||||
QIONetListenerClientFunc func,
|
||||
void *data,
|
||||
AioContext *context);
|
||||
|
||||
/**
|
||||
* qio_net_listener_wait_client:
|
||||
* @listener: the network listener object
|
||||
*
|
||||
* Block execution of the caller until a new client arrives
|
||||
* on one of the listening sockets. If there was previously
|
||||
* a callback registered with qio_net_listener_set_client_func
|
||||
* it will be temporarily disabled, and re-enabled afterwards.
|
||||
*
|
||||
* Returns: the new client socket
|
||||
*/
|
||||
QIOChannelSocket *qio_net_listener_wait_client(QIONetListener *listener);
|
||||
|
||||
|
||||
/**
|
||||
* qio_net_listener_disconnect:
|
||||
* @listener: the network listener object
|
||||
*
|
||||
* Disconnect the listener, removing all I/O callback
|
||||
* watches and closing the socket channels.
|
||||
*/
|
||||
void qio_net_listener_disconnect(QIONetListener *listener);
|
||||
|
||||
|
||||
/**
|
||||
* qio_net_listener_is_connected:
|
||||
* @listener: the network listener object
|
||||
*
|
||||
* Determine if the listener is connected to any socket
|
||||
* channels
|
||||
*
|
||||
* Returns: true if connected, false otherwise
|
||||
*/
|
||||
bool qio_net_listener_is_connected(QIONetListener *listener);
|
||||
|
||||
|
||||
/**
|
||||
* qio_net_listener_nsioc:
|
||||
* @listener: the network listener object
|
||||
*
|
||||
* Determine the number of listener channels currently owned by the
|
||||
* given listener.
|
||||
*
|
||||
* Returns: number of channels, or 0 if not listening
|
||||
*/
|
||||
size_t qio_net_listener_nsioc(QIONetListener *listener);
|
||||
|
||||
|
||||
/**
|
||||
* qio_net_listener_sioc:
|
||||
* @listener: the network listener object
|
||||
* @n: index of the sioc to grab
|
||||
*
|
||||
* Accessor for the nth sioc owned by the listener.
|
||||
*
|
||||
* Returns: the requested listener, or NULL if not in bounds
|
||||
*/
|
||||
QIOChannelSocket *qio_net_listener_sioc(QIONetListener *listener, size_t n);
|
||||
|
||||
/**
|
||||
* qio_net_listener_get_local_address:
|
||||
* @listener: the network listener object
|
||||
* @n: index of the sioc to grab
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Get the string representation of the local socket
|
||||
* address. A pointer to the allocated address information
|
||||
* struct will be returned, which the caller is required to
|
||||
* release with a call qapi_free_SocketAddress() when no
|
||||
* longer required.
|
||||
*
|
||||
* Returns: the socket address struct, or NULL on error
|
||||
*/
|
||||
SocketAddress *
|
||||
qio_net_listener_get_local_address(QIONetListener *listener, size_t n,
|
||||
Error **errp);
|
||||
|
||||
#endif /* QIO_NET_LISTENER_H */
|
||||
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
* QEMU I/O task
|
||||
*
|
||||
* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QIO_TASK_H
|
||||
#define QIO_TASK_H
|
||||
|
||||
typedef struct QIOTask QIOTask;
|
||||
|
||||
typedef void (*QIOTaskFunc)(QIOTask *task,
|
||||
gpointer opaque);
|
||||
|
||||
typedef void (*QIOTaskWorker)(QIOTask *task,
|
||||
gpointer opaque);
|
||||
|
||||
/**
|
||||
* QIOTask:
|
||||
*
|
||||
* The QIOTask object provides a simple mechanism for reporting
|
||||
* success / failure of long running background operations.
|
||||
*
|
||||
* A object on which the operation is to be performed could have
|
||||
* a public API which accepts a task callback:
|
||||
*
|
||||
* <example>
|
||||
* <title>Task function signature</title>
|
||||
* <programlisting>
|
||||
* void myobject_operation(QMyObject *obj,
|
||||
* QIOTaskFunc *func,
|
||||
* gpointer opaque,
|
||||
* GDestroyNotify notify);
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
* The 'func' parameter is the callback to be invoked, and 'opaque'
|
||||
* is data to pass to it. The optional 'notify' function is used
|
||||
* to free 'opaque' when no longer needed.
|
||||
*
|
||||
* When the operation completes, the 'func' callback will be
|
||||
* invoked, allowing the calling code to determine the result
|
||||
* of the operation. An example QIOTaskFunc implementation may
|
||||
* look like
|
||||
*
|
||||
* <example>
|
||||
* <title>Task callback implementation</title>
|
||||
* <programlisting>
|
||||
* static void myobject_operation_notify(QIOTask *task,
|
||||
* gpointer opaque)
|
||||
* {
|
||||
* Error *err = NULL;
|
||||
* if (qio_task_propagate_error(task, &err)) {
|
||||
* ...deal with the failure...
|
||||
* error_free(err);
|
||||
* } else {
|
||||
* QMyObject *src = QMY_OBJECT(qio_task_get_source(task));
|
||||
* ...deal with the completion...
|
||||
* }
|
||||
* }
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
* Now, lets say the implementation of the method using the
|
||||
* task wants to set a timer to run once a second checking
|
||||
* for completion of some activity. It would do something
|
||||
* like
|
||||
*
|
||||
* <example>
|
||||
* <title>Task function implementation</title>
|
||||
* <programlisting>
|
||||
* void myobject_operation(QMyObject *obj,
|
||||
* QIOTaskFunc *func,
|
||||
* gpointer opaque,
|
||||
* GDestroyNotify notify)
|
||||
* {
|
||||
* QIOTask *task;
|
||||
*
|
||||
* task = qio_task_new(OBJECT(obj), func, opaque, notify);
|
||||
*
|
||||
* g_timeout_add_full(G_PRIORITY_DEFAULT,
|
||||
* 1000,
|
||||
* myobject_operation_timer,
|
||||
* task,
|
||||
* qio_task_free);
|
||||
* }
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
* It could equally have setup a watch on a file descriptor or
|
||||
* created a background thread, or something else entirely.
|
||||
* Notice that the source object is passed to the task, and
|
||||
* QIOTask will hold a reference on that. This ensure that
|
||||
* the QMyObject instance cannot be garbage collected while
|
||||
* the async task is still in progress.
|
||||
*
|
||||
* In this case, myobject_operation_timer will fire after
|
||||
* 3 secs and do
|
||||
*
|
||||
* <example>
|
||||
* <title>Task timer function</title>
|
||||
* <programlisting>
|
||||
* gboolean myobject_operation_timer(gpointer opaque)
|
||||
* {
|
||||
* QIOTask *task = QIO_TASK(opaque);
|
||||
* Error *err = NULL;
|
||||
*
|
||||
* ...check something important...
|
||||
* if (err) {
|
||||
* qio_task_set_error(task, err);
|
||||
* qio_task_complete(task);
|
||||
* return FALSE;
|
||||
* } else if (...work is completed ...) {
|
||||
* qio_task_complete(task);
|
||||
* return FALSE;
|
||||
* }
|
||||
* ...carry on polling ...
|
||||
* return TRUE;
|
||||
* }
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
* The 'qio_task_complete' call in this method will trigger
|
||||
* the callback func 'myobject_operation_notify' shown
|
||||
* earlier to deal with the results.
|
||||
*
|
||||
* Once this function returns FALSE, the task will be freed,
|
||||
* causing it release the ref on QMyObject too.
|
||||
*
|
||||
* The QIOTask module can also be used to perform operations
|
||||
* in a background thread context, while still reporting the
|
||||
* results in the main event thread. This allows code which
|
||||
* cannot easily be rewritten to be asynchronous (such as DNS
|
||||
* lookups) to be easily run non-blocking. Reporting the
|
||||
* results in the main thread context means that the caller
|
||||
* typically does not need to be concerned about thread
|
||||
* safety wrt the BQL.
|
||||
*
|
||||
* For example, the socket_listen() method will block the caller
|
||||
* while DNS lookups take place if given a name, instead of IP
|
||||
* address. The C library often do not provide a practical async
|
||||
* DNS API, so the to get non-blocking DNS lookups in a portable
|
||||
* manner requires use of a thread. So achieve a non-blocking
|
||||
* socket listen using QIOTask would require:
|
||||
*
|
||||
* <example>
|
||||
* static void myobject_listen_worker(QIOTask *task,
|
||||
* gpointer opaque)
|
||||
* {
|
||||
* QMyObject obj = QMY_OBJECT(qio_task_get_source(task));
|
||||
* SocketAddress *addr = opaque;
|
||||
* Error *err = NULL;
|
||||
*
|
||||
* obj->fd = socket_listen(addr, &err);
|
||||
*
|
||||
qio_task_set_error(task, err);
|
||||
* }
|
||||
*
|
||||
* void myobject_listen_async(QMyObject *obj,
|
||||
* SocketAddress *addr,
|
||||
* QIOTaskFunc *func,
|
||||
* gpointer opaque,
|
||||
* GDestroyNotify notify)
|
||||
* {
|
||||
* QIOTask *task;
|
||||
* SocketAddress *addrCopy;
|
||||
*
|
||||
* addrCopy = QAPI_CLONE(SocketAddress, addr);
|
||||
* task = qio_task_new(OBJECT(obj), func, opaque, notify);
|
||||
*
|
||||
* qio_task_run_in_thread(task, myobject_listen_worker,
|
||||
* addrCopy,
|
||||
* qapi_free_SocketAddress);
|
||||
* }
|
||||
* </example>
|
||||
*
|
||||
* NB, The 'func' callback passed into myobject_listen_async
|
||||
* will be invoked from the main event thread, despite the
|
||||
* actual operation being performed in a different thread.
|
||||
*/
|
||||
|
||||
/**
|
||||
* qio_task_new:
|
||||
* @source: the object on which the operation is invoked
|
||||
* @func: the callback to invoke when the task completes
|
||||
* @opaque: opaque data to pass to @func when invoked
|
||||
* @destroy: optional callback to free @opaque
|
||||
*
|
||||
* Creates a new task struct to track completion of a
|
||||
* background operation running on the object @source.
|
||||
* When the operation completes or fails, the callback
|
||||
* @func will be invoked. The callback can access the
|
||||
* 'err' attribute in the task object to determine if
|
||||
* the operation was successful or not.
|
||||
*
|
||||
* The returned task must be released by calling
|
||||
* qio_task_free() when no longer required.
|
||||
*
|
||||
* Returns: the task struct
|
||||
*/
|
||||
QIOTask *qio_task_new(Object *source,
|
||||
QIOTaskFunc func,
|
||||
gpointer opaque,
|
||||
GDestroyNotify destroy);
|
||||
|
||||
/**
|
||||
* qio_task_free:
|
||||
* task: the task object to free
|
||||
*
|
||||
* Free the resources associated with the task. Typically
|
||||
* the qio_task_complete() method will be called immediately
|
||||
* before this to trigger the task callback, however, it is
|
||||
* permissible to free the task in the case of cancellation.
|
||||
* The destroy callback will be used to release the opaque
|
||||
* data provided to qio_task_new().
|
||||
*/
|
||||
void qio_task_free(QIOTask *task);
|
||||
|
||||
/**
|
||||
* qio_task_run_in_thread:
|
||||
* @task: the task struct
|
||||
* @worker: the function to invoke in a thread
|
||||
* @opaque: opaque data to pass to @worker
|
||||
* @destroy: function to free @opaque
|
||||
* @context: the context to run the complete hook. If %NULL, the
|
||||
* default context will be used.
|
||||
*
|
||||
* Run a task in a background thread. When @worker
|
||||
* returns it will call qio_task_complete() in
|
||||
* the thread that is running the main loop associated
|
||||
* with @context.
|
||||
*/
|
||||
void qio_task_run_in_thread(QIOTask *task,
|
||||
QIOTaskWorker worker,
|
||||
gpointer opaque,
|
||||
GDestroyNotify destroy,
|
||||
GMainContext *context);
|
||||
|
||||
|
||||
/**
|
||||
* qio_task_wait_thread:
|
||||
* @task: the task struct
|
||||
*
|
||||
* Wait for completion of a task that was previously
|
||||
* invoked using qio_task_run_in_thread. This MUST
|
||||
* ONLY be invoked if the task has not already
|
||||
* completed, since after the completion callback
|
||||
* is invoked, @task will have been freed.
|
||||
*
|
||||
* To avoid racing with execution of the completion
|
||||
* callback provided with qio_task_new, this method
|
||||
* MUST ONLY be invoked from the thread that is
|
||||
* running the main loop associated with @context
|
||||
* parameter to qio_task_run_in_thread.
|
||||
*
|
||||
* When the thread has completed, the completion
|
||||
* callback provided to qio_task_new will be invoked.
|
||||
* When that callback returns @task will be freed,
|
||||
* so @task must not be referenced after this
|
||||
* method completes.
|
||||
*/
|
||||
void qio_task_wait_thread(QIOTask *task);
|
||||
|
||||
|
||||
/**
|
||||
* qio_task_complete:
|
||||
* @task: the task struct
|
||||
*
|
||||
* Invoke the completion callback for @task. This should typically
|
||||
* only be invoked once on a task, and then qio_task_free() used
|
||||
* to free it.
|
||||
*/
|
||||
void qio_task_complete(QIOTask *task);
|
||||
|
||||
|
||||
/**
|
||||
* qio_task_set_error:
|
||||
* @task: the task struct
|
||||
* @err: pointer to the error, or NULL
|
||||
*
|
||||
* Associate an error with the task, which can later
|
||||
* be retrieved with the qio_task_propagate_error()
|
||||
* method. This method takes ownership of @err, so
|
||||
* it is not valid to access it after this call
|
||||
* completes. If @err is NULL this is a no-op. If
|
||||
* this is call multiple times, only the first
|
||||
* provided @err will be recorded, later ones will
|
||||
* be discarded and freed.
|
||||
*/
|
||||
void qio_task_set_error(QIOTask *task,
|
||||
Error *err);
|
||||
|
||||
|
||||
/**
|
||||
* qio_task_propagate_error:
|
||||
* @task: the task struct
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Propagate the error associated with @task
|
||||
* into @errp.
|
||||
*
|
||||
* Returns: true if an error was propagated, false otherwise
|
||||
*/
|
||||
bool qio_task_propagate_error(QIOTask *task,
|
||||
Error **errp);
|
||||
|
||||
|
||||
/**
|
||||
* qio_task_set_result_pointer:
|
||||
* @task: the task struct
|
||||
* @result: pointer to the result data
|
||||
*
|
||||
* Associate an opaque result with the task,
|
||||
* which can later be retrieved with the
|
||||
* qio_task_get_result_pointer() method
|
||||
*
|
||||
*/
|
||||
void qio_task_set_result_pointer(QIOTask *task,
|
||||
gpointer result,
|
||||
GDestroyNotify notify);
|
||||
|
||||
|
||||
/**
|
||||
* qio_task_get_result_pointer:
|
||||
* @task: the task struct
|
||||
*
|
||||
* Retrieve the opaque result data associated
|
||||
* with the task, if any.
|
||||
*
|
||||
* Returns: the task result, or NULL
|
||||
*/
|
||||
gpointer qio_task_get_result_pointer(QIOTask *task);
|
||||
|
||||
|
||||
/**
|
||||
* qio_task_get_source:
|
||||
* @task: the task struct
|
||||
*
|
||||
* Get the source object associated with the background
|
||||
* task. The caller does not own a reference on the
|
||||
* returned Object, and so should call object_ref()
|
||||
* if it wants to keep the object pointer outside the
|
||||
* lifetime of the QIOTask object.
|
||||
*
|
||||
* Returns: the source object
|
||||
*/
|
||||
Object *qio_task_get_source(QIOTask *task);
|
||||
|
||||
#endif /* QIO_TASK_H */
|
||||
Reference in New Issue
Block a user