Import QEMU upstream snapshot d2e570c

Upstream: https://gitlab.com/qemu-project/qemu.git

Upstream-Commit: d2e570cc0f97b936902a5b1b86b73c0f5998b475
This commit is contained in:
2026-08-31 02:15:30 +02:00
commit cf256aa081
11315 changed files with 3598369 additions and 0 deletions
+59
View File
@@ -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 */
+68
View File
@@ -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 */
+110
View File
@@ -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 */
+55
View File
@@ -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 */
+280
View File
@@ -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 */
+158
View File
@@ -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 */
+75
View File
@@ -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 */
+90
View File
@@ -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 */
+109
View File
@@ -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 */
+1175
View File
File diff suppressed because it is too large Load Diff
+219
View File
@@ -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 */
+253
View File
@@ -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 */
+363
View File
@@ -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 */