|
Packit Service |
ea0369 |
/*
|
|
Packit Service |
ea0369 |
* libvirt-gobject-stream.c: libvirt glib integration
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* Copyright (C) 2008 Daniel P. Berrange
|
|
Packit Service |
ea0369 |
* Copyright (C) 2010-2011 Red Hat, Inc.
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* This library is free software; you can redistribute it and/or
|
|
Packit Service |
ea0369 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit Service |
ea0369 |
* License as published by the Free Software Foundation; either
|
|
Packit Service |
ea0369 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* This library is distributed in the hope that it will be useful,
|
|
Packit Service |
ea0369 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
ea0369 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
ea0369 |
* Lesser General Public License for more details.
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit Service |
ea0369 |
* License along with this library. If not, see
|
|
Packit Service |
ea0369 |
* <http://www.gnu.org/licenses/>.
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* Authors: Daniel P. Berrange <berrange@redhat.com>
|
|
Packit Service |
ea0369 |
* Marc-André Lureau <marcandre.lureau@redhat.com>
|
|
Packit Service |
ea0369 |
*/
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
#include <config.h>
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
#include <libvirt/virterror.h>
|
|
Packit Service |
ea0369 |
#include <string.h>
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
#include <glib/gi18n-lib.h>
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
#include "libvirt-glib/libvirt-glib.h"
|
|
Packit Service |
ea0369 |
#include "libvirt-gobject/libvirt-gobject.h"
|
|
Packit Service |
ea0369 |
#include "libvirt-gobject-compat.h"
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
#include "libvirt-gobject/libvirt-gobject-input-stream.h"
|
|
Packit Service |
ea0369 |
#include "libvirt-gobject/libvirt-gobject-output-stream.h"
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
#define GVIR_STREAM_GET_PRIVATE(obj) \
|
|
Packit Service |
ea0369 |
(G_TYPE_INSTANCE_GET_PRIVATE((obj), GVIR_TYPE_STREAM, GVirStreamPrivate))
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
struct _GVirStreamPrivate
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
virStreamPtr handle;
|
|
Packit Service |
ea0369 |
GInputStream *input_stream;
|
|
Packit Service |
ea0369 |
GOutputStream *output_stream;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
gboolean eventRegistered;
|
|
Packit Service |
ea0369 |
int eventLast;
|
|
Packit Service |
ea0369 |
GList *sources;
|
|
Packit Service |
ea0369 |
};
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
typedef struct {
|
|
Packit Service |
ea0369 |
GSource source;
|
|
Packit Service |
ea0369 |
GVirStreamIOCondition cond;
|
|
Packit Service |
ea0369 |
GVirStreamIOCondition newCond;
|
|
Packit Service |
ea0369 |
GVirStream *stream;
|
|
Packit Service |
ea0369 |
} GVirStreamSource;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
G_DEFINE_TYPE_WITH_PRIVATE(GVirStream, gvir_stream, G_TYPE_IO_STREAM);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
enum {
|
|
Packit Service |
ea0369 |
PROP_0,
|
|
Packit Service |
ea0369 |
PROP_HANDLE,
|
|
Packit Service |
ea0369 |
};
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
#define GVIR_STREAM_ERROR gvir_stream_error_quark()
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static void gvir_stream_update_events(GVirStream *stream);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static GQuark
|
|
Packit Service |
ea0369 |
gvir_stream_error_quark(void)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
return g_quark_from_static_string("gvir-stream");
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static GInputStream* gvir_stream_get_input_stream(GIOStream *io_stream)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
GVirStream *self = GVIR_STREAM(io_stream);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (self->priv->input_stream == NULL)
|
|
Packit Service |
ea0369 |
self->priv->input_stream = (GInputStream *)_gvir_input_stream_new(self);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
return self->priv->input_stream;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static GOutputStream* gvir_stream_get_output_stream(GIOStream *io_stream)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
GVirStream *self = GVIR_STREAM(io_stream);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (self->priv->output_stream == NULL)
|
|
Packit Service |
ea0369 |
self->priv->output_stream = (GOutputStream *)_gvir_output_stream_new(self);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
return self->priv->output_stream;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static gboolean gvir_stream_close(GIOStream *io_stream,
|
|
Packit Service |
ea0369 |
GCancellable *cancellable,
|
|
Packit Service |
ea0369 |
GError **error)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
GVirStream *self = GVIR_STREAM(io_stream);
|
|
Packit Service |
ea0369 |
GError *local_error = NULL;
|
|
Packit Service |
ea0369 |
gboolean i_ret = TRUE, o_ret = TRUE;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (self->priv->input_stream)
|
|
Packit Service |
ea0369 |
i_ret = g_input_stream_close(self->priv->input_stream, cancellable, &local_error);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (local_error)
|
|
Packit Service |
ea0369 |
g_propagate_error(error, local_error);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (self->priv->output_stream)
|
|
Packit Service |
ea0369 |
o_ret = g_output_stream_close(self->priv->output_stream, cancellable, &local_error);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (local_error) {
|
|
Packit Service |
ea0369 |
if (i_ret)
|
|
Packit Service |
ea0369 |
g_propagate_error(error, local_error);
|
|
Packit Service |
ea0369 |
else
|
|
Packit Service |
ea0369 |
g_error_free(local_error);
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
return (i_ret && o_ret);
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static gboolean close_in_idle (gpointer data)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
GTask *task = G_TASK (data);
|
|
Packit Service |
ea0369 |
GIOStream *stream = G_IO_STREAM(g_task_get_source_object (task));
|
|
Packit Service |
ea0369 |
GCancellable *cancellable = g_task_get_cancellable (task);
|
|
Packit Service |
ea0369 |
GIOStreamClass *class;
|
|
Packit Service |
ea0369 |
GError *error;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
class = G_IO_STREAM_GET_CLASS(stream);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
/* close is not blocked, just do it! */
|
|
Packit Service |
ea0369 |
error = NULL;
|
|
Packit Service |
ea0369 |
if (class->close_fn &&
|
|
Packit Service |
ea0369 |
!class->close_fn(stream, cancellable, &error)) {
|
|
Packit Service |
ea0369 |
g_task_return_error(task, error);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
goto exit;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
g_task_return_boolean(task, TRUE);
|
|
Packit Service |
ea0369 |
exit:
|
|
Packit Service |
ea0369 |
g_object_unref(task);
|
|
Packit Service |
ea0369 |
return FALSE;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static void gvir_stream_close_async(GIOStream *stream,
|
|
Packit Service |
ea0369 |
int io_priority G_GNUC_UNUSED,
|
|
Packit Service |
ea0369 |
GCancellable *cancellable,
|
|
Packit Service |
ea0369 |
GAsyncReadyCallback callback,
|
|
Packit Service |
ea0369 |
gpointer user_data)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
GTask *task;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
task = g_task_new(G_OBJECT(stream),
|
|
Packit Service |
ea0369 |
cancellable,
|
|
Packit Service |
ea0369 |
callback,
|
|
Packit Service |
ea0369 |
user_data);
|
|
Packit Service |
ea0369 |
g_idle_add(close_in_idle, task);
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static gboolean
|
|
Packit Service |
ea0369 |
gvir_stream_close_finish(GIOStream *stream,
|
|
Packit Service |
ea0369 |
GAsyncResult *result,
|
|
Packit Service |
ea0369 |
GError **error)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
g_return_val_if_fail(GVIR_IS_STREAM(stream), FALSE);
|
|
Packit Service |
ea0369 |
g_return_val_if_fail(g_task_is_valid(result, stream), FALSE);
|
|
Packit Service |
ea0369 |
g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
return g_task_propagate_boolean(G_TASK(result), error);
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static void gvir_stream_get_property(GObject *object,
|
|
Packit Service |
ea0369 |
guint prop_id,
|
|
Packit Service |
ea0369 |
GValue *value,
|
|
Packit Service |
ea0369 |
GParamSpec *pspec)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
GVirStream *self = GVIR_STREAM(object);
|
|
Packit Service |
ea0369 |
GVirStreamPrivate *priv = self->priv;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
switch (prop_id) {
|
|
Packit Service |
ea0369 |
case PROP_HANDLE:
|
|
Packit Service |
ea0369 |
g_value_set_boxed(value, priv->handle);
|
|
Packit Service |
ea0369 |
break;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
default:
|
|
Packit Service |
ea0369 |
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static void gvir_stream_set_property(GObject *object,
|
|
Packit Service |
ea0369 |
guint prop_id,
|
|
Packit Service |
ea0369 |
const GValue *value,
|
|
Packit Service |
ea0369 |
GParamSpec *pspec)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
GVirStream *self = GVIR_STREAM(object);
|
|
Packit Service |
ea0369 |
GVirStreamPrivate *priv = self->priv;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
switch (prop_id) {
|
|
Packit Service |
ea0369 |
case PROP_HANDLE:
|
|
Packit Service |
ea0369 |
if (priv->handle)
|
|
Packit Service |
ea0369 |
virStreamFree(priv->handle);
|
|
Packit Service |
ea0369 |
priv->handle = g_value_get_boxed(value);
|
|
Packit Service |
ea0369 |
break;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
default:
|
|
Packit Service |
ea0369 |
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static void gvir_stream_finalize(GObject *object)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
GVirStream *self = GVIR_STREAM(object);
|
|
Packit Service |
ea0369 |
GVirStreamPrivate *priv = self->priv;
|
|
Packit Service |
ea0369 |
GList *tmp;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (self->priv->input_stream)
|
|
Packit Service |
ea0369 |
g_object_unref(self->priv->input_stream);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
tmp = priv->sources;
|
|
Packit Service |
ea0369 |
while (tmp) {
|
|
Packit Service |
ea0369 |
GVirStreamSource *source = tmp->data;
|
|
Packit Service |
ea0369 |
g_source_destroy((GSource*)source);
|
|
Packit Service |
ea0369 |
tmp = tmp->next;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
g_list_free(priv->sources);
|
|
Packit Service |
ea0369 |
priv->sources = NULL;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (priv->handle) {
|
|
Packit Service |
ea0369 |
gvir_stream_update_events(self);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (virStreamFinish(priv->handle) < 0)
|
|
Packit Service |
ea0369 |
gvir_critical("cannot finish stream");
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
virStreamFree(priv->handle);
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
G_OBJECT_CLASS(gvir_stream_parent_class)->finalize(object);
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static void gvir_stream_class_init(GVirStreamClass *klass)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
Packit Service |
ea0369 |
GIOStreamClass *stream_class = G_IO_STREAM_CLASS(klass);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
object_class->finalize = gvir_stream_finalize;
|
|
Packit Service |
ea0369 |
object_class->get_property = gvir_stream_get_property;
|
|
Packit Service |
ea0369 |
object_class->set_property = gvir_stream_set_property;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
stream_class->get_input_stream = gvir_stream_get_input_stream;
|
|
Packit Service |
ea0369 |
stream_class->get_output_stream = gvir_stream_get_output_stream;
|
|
Packit Service |
ea0369 |
stream_class->close_fn = gvir_stream_close;
|
|
Packit Service |
ea0369 |
stream_class->close_async = gvir_stream_close_async;
|
|
Packit Service |
ea0369 |
stream_class->close_finish = gvir_stream_close_finish;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
g_object_class_install_property(object_class,
|
|
Packit Service |
ea0369 |
PROP_HANDLE,
|
|
Packit Service |
ea0369 |
g_param_spec_boxed("handle",
|
|
Packit Service |
ea0369 |
"Handle",
|
|
Packit Service |
ea0369 |
"The stream handle",
|
|
Packit Service |
ea0369 |
GVIR_TYPE_STREAM_HANDLE,
|
|
Packit Service |
ea0369 |
G_PARAM_READABLE |
|
|
Packit Service |
ea0369 |
G_PARAM_WRITABLE |
|
|
Packit Service |
ea0369 |
G_PARAM_CONSTRUCT_ONLY |
|
|
Packit Service |
ea0369 |
G_PARAM_STATIC_STRINGS));
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static void gvir_stream_init(GVirStream *self)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
self->priv = GVIR_STREAM_GET_PRIVATE(self);
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
typedef struct virStream GVirStreamHandle;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static GVirStreamHandle*
|
|
Packit Service |
ea0369 |
gvir_stream_handle_copy(GVirStreamHandle *src)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
virStreamRef((virStreamPtr)src);
|
|
Packit Service |
ea0369 |
return src;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static void
|
|
Packit Service |
ea0369 |
gvir_stream_handle_free(GVirStreamHandle *src)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
virStreamFree((virStreamPtr)src);
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
G_DEFINE_BOXED_TYPE(GVirStreamHandle, gvir_stream_handle,
|
|
Packit Service |
ea0369 |
gvir_stream_handle_copy, gvir_stream_handle_free)
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
/**
|
|
Packit Service |
ea0369 |
* gvir_stream_receive:
|
|
Packit Service |
ea0369 |
* @stream: the stream
|
|
Packit Service |
ea0369 |
* @buffer: (array length=size) (element-type guint8): a buffer
|
|
Packit Service |
ea0369 |
* to read data into (which should be at least @size bytes long).
|
|
Packit Service |
ea0369 |
* @size: the number of bytes you want to read from the stream
|
|
Packit Service |
ea0369 |
* @cancellable: (allow-none): a %GCancellable or %NULL
|
|
Packit Service |
ea0369 |
* @error: #GError for error reporting, or %NULL to ignore.
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* Receive data (up to @size bytes) from a stream.
|
|
Packit Service |
ea0369 |
* On error -1 is returned and @error is set accordingly.
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* gvir_stream_receive() can return any number of bytes, up to
|
|
Packit Service |
ea0369 |
* @size. If more than @size bytes have been received, the additional
|
|
Packit Service |
ea0369 |
* data will be returned in future calls to gvir_stream_receive().
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* If there is no data available, a %G_IO_ERROR_WOULD_BLOCK error will be
|
|
Packit Service |
ea0369 |
* returned.
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* Returns: Number of bytes read, or 0 if the end of stream reached,
|
|
Packit Service |
ea0369 |
* or -1 on error.
|
|
Packit Service |
ea0369 |
*/
|
|
Packit Service |
ea0369 |
gssize gvir_stream_receive(GVirStream *self,
|
|
Packit Service |
ea0369 |
gchar *buffer,
|
|
Packit Service |
ea0369 |
gsize size,
|
|
Packit Service |
ea0369 |
GCancellable *cancellable,
|
|
Packit Service |
ea0369 |
GError **error)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
int got;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
g_return_val_if_fail(GVIR_IS_STREAM(self), -1);
|
|
Packit Service |
ea0369 |
g_return_val_if_fail(buffer != NULL, -1);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
|
Packit Service |
ea0369 |
return -1;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
got = virStreamRecv(self->priv->handle, buffer, size);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (got == -2) { /* blocking */
|
|
Packit Service |
ea0369 |
g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
|
|
Packit Service |
ea0369 |
_("virStreamRecv call would block"));
|
|
Packit Service |
ea0369 |
} else if (got < 0) {
|
|
Packit Service |
ea0369 |
g_set_error(error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
|
|
Packit Service |
ea0369 |
_("Got virStreamRecv error in %s"), G_STRFUNC);
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
return got;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
struct stream_sink_helper {
|
|
Packit Service |
ea0369 |
GVirStream *self;
|
|
Packit Service |
ea0369 |
GVirStreamSinkFunc func;
|
|
Packit Service |
ea0369 |
gpointer user_data;
|
|
Packit Service |
ea0369 |
GCancellable *cancellable;
|
|
Packit Service |
ea0369 |
};
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static int
|
|
Packit Service |
ea0369 |
stream_sink(virStreamPtr st G_GNUC_UNUSED,
|
|
Packit Service |
ea0369 |
const char *bytes,
|
|
Packit Service |
ea0369 |
size_t nbytes,
|
|
Packit Service |
ea0369 |
void *opaque)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
struct stream_sink_helper *helper = opaque;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (g_cancellable_is_cancelled(helper->cancellable))
|
|
Packit Service |
ea0369 |
return -1;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
return helper->func(helper->self, bytes, nbytes, helper->user_data);
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
/**
|
|
Packit Service |
ea0369 |
* gvir_stream_receive_all:
|
|
Packit Service |
ea0369 |
* @stream: the stream
|
|
Packit Service |
ea0369 |
* @cancellable: cancellation notifier
|
|
Packit Service |
ea0369 |
* @func: (scope notified): the callback for writing data to application
|
|
Packit Service |
ea0369 |
* @user_data: (closure): data to be passed to @callback
|
|
Packit Service |
ea0369 |
* @error: #GError for error reporting, or %NULL to ignore.
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* Receive the entire data stream, sending the data to the
|
|
Packit Service |
ea0369 |
* requested data sink. This is simply a convenient alternative
|
|
Packit Service |
ea0369 |
* to virStreamRecv, for apps that do blocking-I/o.
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* Returns: the number of bytes consumed or -1 upon error
|
|
Packit Service |
ea0369 |
*/
|
|
Packit Service |
ea0369 |
gssize
|
|
Packit Service |
ea0369 |
gvir_stream_receive_all(GVirStream *self,
|
|
Packit Service |
ea0369 |
GCancellable *cancellable,
|
|
Packit Service |
ea0369 |
GVirStreamSinkFunc func,
|
|
Packit Service |
ea0369 |
gpointer user_data,
|
|
Packit Service |
ea0369 |
GError **error)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
struct stream_sink_helper helper = {
|
|
Packit Service |
ea0369 |
.self = self,
|
|
Packit Service |
ea0369 |
.func = func,
|
|
Packit Service |
ea0369 |
.user_data = user_data,
|
|
Packit Service |
ea0369 |
.cancellable = cancellable,
|
|
Packit Service |
ea0369 |
};
|
|
Packit Service |
ea0369 |
int r;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
g_return_val_if_fail(GVIR_IS_STREAM(self), -1);
|
|
Packit Service |
ea0369 |
g_return_val_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable), -1);
|
|
Packit Service |
ea0369 |
g_return_val_if_fail(func != NULL, -1);
|
|
Packit Service |
ea0369 |
g_return_val_if_fail(error == NULL || *error == NULL, -1);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
r = virStreamRecvAll(self->priv->handle, stream_sink, &helper);
|
|
Packit Service |
ea0369 |
if (r < 0) {
|
|
Packit Service |
ea0369 |
gvir_set_error_literal(error, GVIR_STREAM_ERROR,
|
|
Packit Service |
ea0369 |
0,
|
|
Packit Service |
ea0369 |
_("Unable to perform RecvAll"));
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
return r;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
/**
|
|
Packit Service |
ea0369 |
* gvir_stream_send:
|
|
Packit Service |
ea0369 |
* @stream: the stream
|
|
Packit Service |
ea0369 |
* @buffer: a buffer to write data from (which should be at least @size
|
|
Packit Service |
ea0369 |
* bytes long).
|
|
Packit Service |
ea0369 |
* @size: the number of bytes you want to write to the stream
|
|
Packit Service |
ea0369 |
* @cancellable: (allow-none): a %GCancellable or %NULL
|
|
Packit Service |
ea0369 |
* @error: #GError for error reporting, or %NULL to ignore.
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* Send data (up to @size bytes) from a stream.
|
|
Packit Service |
ea0369 |
* On error -1 is returned and @error is set accordingly.
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* gvir_stream_send() can return any number of bytes, up to
|
|
Packit Service |
ea0369 |
* @size. If more than @size bytes have been sendd, the additional
|
|
Packit Service |
ea0369 |
* data will be returned in future calls to gvir_stream_send().
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* If there is no data available, a %G_IO_ERROR_WOULD_BLOCK error will be
|
|
Packit Service |
ea0369 |
* returned.
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* Returns: Number of bytes written.
|
|
Packit Service |
ea0369 |
*/
|
|
Packit Service |
ea0369 |
gssize gvir_stream_send(GVirStream *self,
|
|
Packit Service |
ea0369 |
const gchar *buffer,
|
|
Packit Service |
ea0369 |
gsize size,
|
|
Packit Service |
ea0369 |
GCancellable *cancellable,
|
|
Packit Service |
ea0369 |
GError **error)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
int got;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
g_return_val_if_fail(GVIR_IS_STREAM(self), -1);
|
|
Packit Service |
ea0369 |
g_return_val_if_fail(buffer != NULL, -1);
|
|
Packit Service |
ea0369 |
g_return_val_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable), -1);
|
|
Packit Service |
ea0369 |
g_return_val_if_fail(error == NULL || *error == NULL, -1);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
|
Packit Service |
ea0369 |
return -1;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
got = virStreamSend(self->priv->handle, buffer, size);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (got == -2) { /* blocking */
|
|
Packit Service |
ea0369 |
g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
|
|
Packit Service |
ea0369 |
_("virStreamSend call would block"));
|
|
Packit Service |
ea0369 |
} else if (got < 0) {
|
|
Packit Service |
ea0369 |
g_set_error(error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
|
|
Packit Service |
ea0369 |
_("Got virStreamRecv error in %s"), G_STRFUNC);
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
return got;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
struct stream_source_helper {
|
|
Packit Service |
ea0369 |
GVirStream *self;
|
|
Packit Service |
ea0369 |
GVirStreamSourceFunc func;
|
|
Packit Service |
ea0369 |
gpointer user_data;
|
|
Packit Service |
ea0369 |
GCancellable *cancellable;
|
|
Packit Service |
ea0369 |
};
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static int
|
|
Packit Service |
ea0369 |
stream_source(virStreamPtr st G_GNUC_UNUSED,
|
|
Packit Service |
ea0369 |
char *bytes,
|
|
Packit Service |
ea0369 |
size_t nbytes,
|
|
Packit Service |
ea0369 |
void *opaque)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
struct stream_source_helper *helper = opaque;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (g_cancellable_is_cancelled(helper->cancellable))
|
|
Packit Service |
ea0369 |
return -1;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
return helper->func(helper->self, bytes, nbytes, helper->user_data);
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
/**
|
|
Packit Service |
ea0369 |
* gvir_stream_send_all:
|
|
Packit Service |
ea0369 |
* @stream: the stream
|
|
Packit Service |
ea0369 |
* @cancellable: cancellation notifier
|
|
Packit Service |
ea0369 |
* @func: (scope notified): the callback for writing data to application
|
|
Packit Service |
ea0369 |
* @user_data: (closure): data to be passed to @callback
|
|
Packit Service |
ea0369 |
* @error: #GError for error reporting, or %NULL to ignore.
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* Send the entire data stream, sending the data to the
|
|
Packit Service |
ea0369 |
* requested data source. This is simply a convenient alternative
|
|
Packit Service |
ea0369 |
* to virStreamRecv, for apps that do blocking-I/o.
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* Returns: the number of bytes consumed or -1 upon error
|
|
Packit Service |
ea0369 |
*/
|
|
Packit Service |
ea0369 |
gssize
|
|
Packit Service |
ea0369 |
gvir_stream_send_all(GVirStream *self,
|
|
Packit Service |
ea0369 |
GCancellable *cancellable,
|
|
Packit Service |
ea0369 |
GVirStreamSourceFunc func,
|
|
Packit Service |
ea0369 |
gpointer user_data,
|
|
Packit Service |
ea0369 |
GError **error)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
struct stream_source_helper helper = {
|
|
Packit Service |
ea0369 |
.self = self,
|
|
Packit Service |
ea0369 |
.func = func,
|
|
Packit Service |
ea0369 |
.user_data = user_data,
|
|
Packit Service |
ea0369 |
.cancellable = cancellable,
|
|
Packit Service |
ea0369 |
};
|
|
Packit Service |
ea0369 |
int r;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
g_return_val_if_fail(GVIR_IS_STREAM(self), -1);
|
|
Packit Service |
ea0369 |
g_return_val_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable), -1);
|
|
Packit Service |
ea0369 |
g_return_val_if_fail(func != NULL, -1);
|
|
Packit Service |
ea0369 |
g_return_val_if_fail(error == NULL || *error == NULL, -1);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
r = virStreamSendAll(self->priv->handle, stream_source, &helper);
|
|
Packit Service |
ea0369 |
if (r < 0) {
|
|
Packit Service |
ea0369 |
gvir_set_error_literal(error, GVIR_STREAM_ERROR,
|
|
Packit Service |
ea0369 |
0,
|
|
Packit Service |
ea0369 |
_("Unable to perform SendAll"));
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
return r;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static void gvir_stream_handle_events(virStreamPtr st G_GNUC_UNUSED,
|
|
Packit Service |
ea0369 |
int events,
|
|
Packit Service |
ea0369 |
void *opaque)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
GVirStream *stream = GVIR_STREAM(opaque);
|
|
Packit Service |
ea0369 |
GVirStreamPrivate *priv = stream->priv;
|
|
Packit Service |
ea0369 |
GList *tmp = priv->sources;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
while (tmp) {
|
|
Packit Service |
ea0369 |
GVirStreamSource *source = tmp->data;
|
|
Packit Service |
ea0369 |
source->newCond = 0;
|
|
Packit Service |
ea0369 |
if (source->cond & GVIR_STREAM_IO_CONDITION_READABLE) {
|
|
Packit Service |
ea0369 |
if (events & VIR_STREAM_EVENT_READABLE)
|
|
Packit Service |
ea0369 |
source->newCond |= GVIR_STREAM_IO_CONDITION_READABLE;
|
|
Packit Service |
ea0369 |
if (events & VIR_STREAM_EVENT_HANGUP)
|
|
Packit Service |
ea0369 |
source->newCond |= GVIR_STREAM_IO_CONDITION_HANGUP;
|
|
Packit Service |
ea0369 |
if (events & VIR_STREAM_EVENT_ERROR)
|
|
Packit Service |
ea0369 |
source->newCond |= GVIR_STREAM_IO_CONDITION_ERROR;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
if (source->cond & GVIR_STREAM_IO_CONDITION_WRITABLE) {
|
|
Packit Service |
ea0369 |
if (events & VIR_STREAM_EVENT_WRITABLE)
|
|
Packit Service |
ea0369 |
source->newCond |= GVIR_STREAM_IO_CONDITION_WRITABLE;
|
|
Packit Service |
ea0369 |
if (events & VIR_STREAM_EVENT_HANGUP)
|
|
Packit Service |
ea0369 |
source->newCond |= GVIR_STREAM_IO_CONDITION_HANGUP;
|
|
Packit Service |
ea0369 |
if (events & VIR_STREAM_EVENT_ERROR)
|
|
Packit Service |
ea0369 |
source->newCond |= GVIR_STREAM_IO_CONDITION_ERROR;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
tmp = tmp->next;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static void gvir_stream_update_events(GVirStream *stream)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
GVirStreamPrivate *priv = stream->priv;
|
|
Packit Service |
ea0369 |
int mask = 0;
|
|
Packit Service |
ea0369 |
GList *tmp = priv->sources;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
while (tmp) {
|
|
Packit Service |
ea0369 |
GVirStreamSource *source = tmp->data;
|
|
Packit Service |
ea0369 |
if (source->cond & GVIR_STREAM_IO_CONDITION_READABLE)
|
|
Packit Service |
ea0369 |
mask |= VIR_STREAM_EVENT_READABLE;
|
|
Packit Service |
ea0369 |
if (source->cond & GVIR_STREAM_IO_CONDITION_WRITABLE)
|
|
Packit Service |
ea0369 |
mask |= VIR_STREAM_EVENT_WRITABLE;
|
|
Packit Service |
ea0369 |
tmp = tmp->next;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (mask) {
|
|
Packit Service |
ea0369 |
if (priv->eventRegistered) {
|
|
Packit Service |
ea0369 |
virStreamEventUpdateCallback(priv->handle, mask);
|
|
Packit Service |
ea0369 |
} else {
|
|
Packit Service |
ea0369 |
virStreamEventAddCallback(priv->handle, mask,
|
|
Packit Service |
ea0369 |
gvir_stream_handle_events,
|
|
Packit Service |
ea0369 |
stream,
|
|
Packit Service |
ea0369 |
NULL);
|
|
Packit Service |
ea0369 |
priv->eventRegistered = TRUE;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
} else {
|
|
Packit Service |
ea0369 |
if (priv->eventRegistered) {
|
|
Packit Service |
ea0369 |
virStreamEventRemoveCallback(priv->handle);
|
|
Packit Service |
ea0369 |
priv->eventRegistered = FALSE;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static gboolean gvir_stream_source_prepare(GSource *source,
|
|
Packit Service |
ea0369 |
gint *timeout)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
GVirStreamSource *gsource = (GVirStreamSource*)source;
|
|
Packit Service |
ea0369 |
if (gsource->newCond) {
|
|
Packit Service |
ea0369 |
*timeout = 0;
|
|
Packit Service |
ea0369 |
return TRUE;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
*timeout = -1;
|
|
Packit Service |
ea0369 |
return FALSE;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static gboolean gvir_stream_source_check(GSource *source)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
GVirStreamSource *gsource = (GVirStreamSource*)source;
|
|
Packit Service |
ea0369 |
if (gsource->newCond)
|
|
Packit Service |
ea0369 |
return TRUE;
|
|
Packit Service |
ea0369 |
return FALSE;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static gboolean gvir_stream_source_dispatch(GSource *source,
|
|
Packit Service |
ea0369 |
GSourceFunc callback,
|
|
Packit Service |
ea0369 |
gpointer user_data)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
GVirStreamSource *gsource = (GVirStreamSource*)source;
|
|
Packit Service |
ea0369 |
GVirStreamIOFunc func = (GVirStreamIOFunc)callback;
|
|
Packit Service |
ea0369 |
gboolean ret;
|
|
Packit Service |
ea0369 |
ret = func(gsource->stream, gsource->newCond, user_data);
|
|
Packit Service |
ea0369 |
gsource->newCond = 0;
|
|
Packit Service |
ea0369 |
return ret;
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
static void gvir_stream_source_finalize(GSource *source)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
GVirStreamSource *gsource = (GVirStreamSource*)source;
|
|
Packit Service |
ea0369 |
GVirStreamPrivate *priv = gsource->stream->priv;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
priv->sources = g_list_remove(priv->sources, source);
|
|
Packit Service |
ea0369 |
gvir_stream_update_events(gsource->stream);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
g_clear_object(&gsource->stream);
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
GSourceFuncs gvir_stream_source_funcs = {
|
|
Packit Service |
ea0369 |
.prepare = gvir_stream_source_prepare,
|
|
Packit Service |
ea0369 |
.check = gvir_stream_source_check,
|
|
Packit Service |
ea0369 |
.dispatch = gvir_stream_source_dispatch,
|
|
Packit Service |
ea0369 |
.finalize = gvir_stream_source_finalize,
|
|
Packit Service |
ea0369 |
};
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
/**
|
|
Packit Service |
ea0369 |
* gvir_stream_add_watch: (skip)
|
|
Packit Service |
ea0369 |
* @stream: the stream
|
|
Packit Service |
ea0369 |
* @cond: the conditions to watch for (bitfield of #GVirStreamIOCondition)
|
|
Packit Service |
ea0369 |
* @func: (closure opaque): the function to call when the condition is satisfied
|
|
Packit Service |
ea0369 |
* @opaque: (closure): user data to pass to @func
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* Adds a watch for @stream to the mainloop
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* Returns: the event source id
|
|
Packit Service |
ea0369 |
*/
|
|
Packit Service |
ea0369 |
guint gvir_stream_add_watch(GVirStream *stream,
|
|
Packit Service |
ea0369 |
GVirStreamIOCondition cond,
|
|
Packit Service |
ea0369 |
GVirStreamIOFunc func,
|
|
Packit Service |
ea0369 |
gpointer opaque)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
return gvir_stream_add_watch_full(stream,
|
|
Packit Service |
ea0369 |
G_PRIORITY_DEFAULT,
|
|
Packit Service |
ea0369 |
cond,
|
|
Packit Service |
ea0369 |
func,
|
|
Packit Service |
ea0369 |
opaque,
|
|
Packit Service |
ea0369 |
NULL);
|
|
Packit Service |
ea0369 |
}
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
/**
|
|
Packit Service |
ea0369 |
* gvir_stream_add_watch_full: (rename-to gvir_stream_add_watch)
|
|
Packit Service |
ea0369 |
* @stream: the stream
|
|
Packit Service |
ea0369 |
* @priority: the priority of the #GVirStream source
|
|
Packit Service |
ea0369 |
* @cond: the conditions to watch for (bitfield of #GVirStreamIOCondition)
|
|
Packit Service |
ea0369 |
* @func: (closure opaque): the function to call when the condition is satisfied
|
|
Packit Service |
ea0369 |
* @opaque: (closure): user data to pass to @func
|
|
Packit Service |
ea0369 |
* @notify: the function to call when the source is removed
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* Adds a watch for @stream to the mainloop
|
|
Packit Service |
ea0369 |
*
|
|
Packit Service |
ea0369 |
* Returns: the event source id
|
|
Packit Service |
ea0369 |
*/
|
|
Packit Service |
ea0369 |
guint gvir_stream_add_watch_full(GVirStream *stream,
|
|
Packit Service |
ea0369 |
gint priority,
|
|
Packit Service |
ea0369 |
GVirStreamIOCondition cond,
|
|
Packit Service |
ea0369 |
GVirStreamIOFunc func,
|
|
Packit Service |
ea0369 |
gpointer opaque,
|
|
Packit Service |
ea0369 |
GDestroyNotify notify)
|
|
Packit Service |
ea0369 |
{
|
|
Packit Service |
ea0369 |
g_return_val_if_fail(GVIR_IS_STREAM(stream), 0);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
GVirStreamPrivate *priv = stream->priv;
|
|
Packit Service |
ea0369 |
GVirStreamSource *source = (GVirStreamSource*)g_source_new(&gvir_stream_source_funcs,
|
|
Packit Service |
ea0369 |
sizeof(GVirStreamSource));
|
|
Packit Service |
ea0369 |
guint ret;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
source->stream = g_object_ref(stream);
|
|
Packit Service |
ea0369 |
source->cond = cond;
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
if (priority != G_PRIORITY_DEFAULT)
|
|
Packit Service |
ea0369 |
g_source_set_priority((GSource*)source, priority);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
priv->sources = g_list_append(priv->sources, source);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
gvir_stream_update_events(source->stream);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
g_source_set_callback((GSource*)source, (GSourceFunc)func, opaque, notify);
|
|
Packit Service |
ea0369 |
ret = g_source_attach((GSource*)source, g_main_context_default());
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
g_source_unref((GSource*)source);
|
|
Packit Service |
ea0369 |
|
|
Packit Service |
ea0369 |
return ret;
|
|
Packit Service |
ea0369 |
}
|