Commit 84a95ec9 authored by Daniel P. Berrange's avatar Daniel P. Berrange

Move interactive console to a separate console device

To avoid mixing the interactive console I/O with the machine
boot/error messages, use a dedicated console device for
interactive apps. Run a XDR based RPC protocol over the
console device to allow proper separation of stdout and
stderr, and passing back of command exit status
parent 15fb0b7e
......@@ -38,6 +38,8 @@ libvirt-sandbox/libvirt-sandbox-init-common
libvirt-sandbox/libvirt-sandbox-init-qemu
libvirt-sandbox/libvirt-sandbox-enum-types.h
libvirt-sandbox/libvirt-sandbox-enum-types.c
libvirt-sandbox/libvirt-sandbox-protocol.c
libvirt-sandbox/libvirt-sandbox-protocol.h
libvirt-sandbox/tests/*.cfg
libvirt-sandbox/tests/test-config
bin/virt-sandbox
......
......@@ -34,6 +34,15 @@ static gboolean do_close(GVirSandboxConsole *con G_GNUC_UNUSED,
return FALSE;
}
static gboolean do_exited(GVirSandboxConsole *con G_GNUC_UNUSED,
int status,
gpointer opaque)
{
int *ret = opaque;
*ret = WEXITSTATUS(status);
return FALSE;
}
static void libvirt_sandbox_version(void)
{
g_print(_("%s version %s\n"), PACKAGE, VERSION);
......@@ -49,6 +58,7 @@ int main(int argc, char **argv) {
GVirSandboxConfigInteractive *icfg = NULL;
GVirSandboxContext *ctx = NULL;
GVirSandboxContextInteractive *ictx = NULL;
GVirSandboxConsole *log = NULL;
GVirSandboxConsole *con = NULL;
GMainLoop *loop = NULL;
GError *error = NULL;
......@@ -209,12 +219,26 @@ int main(int argc, char **argv) {
goto cleanup;
}
if (!(con = gvir_sandbox_context_get_log_console(ctx, &error))) {
if (!(log = gvir_sandbox_context_get_log_console(ctx, &error))) {
g_printerr(_("Unable to get log console: %s\n"),
error && error->message ? error->message : "unknown");
goto cleanup;
}
g_signal_connect(log, "closed", (GCallback)do_close, loop);
if (!(gvir_sandbox_console_attach_stderr(log, &error))) {
g_printerr(_("Unable to attach sandbox console: %s\n"),
error && error->message ? error->message : "unknown");
goto cleanup;
}
if (!(con = gvir_sandbox_context_interactive_get_app_console(ictx, &error))) {
g_printerr(_("Unable to get app console: %s\n"),
error && error->message ? error->message : "unknown");
goto cleanup;
}
g_signal_connect(con, "closed", (GCallback)do_close, loop);
g_signal_connect(con, "exited", (GCallback)do_exited, &ret);
if (!(gvir_sandbox_console_attach_stdio(con, &error))) {
g_printerr(_("Unable to attach sandbox console: %s\n"),
......@@ -224,8 +248,6 @@ int main(int argc, char **argv) {
g_main_loop_run(loop);
ret = EXIT_SUCCESS;
cleanup:
if (error)
g_error_free(error);
......@@ -241,6 +263,7 @@ cleanup:
g_main_loop_unref(loop);
if (hv)
g_object_unref(hv);
return ret;
}
......
......@@ -51,6 +51,7 @@ LIBVIRT_SANDBOX_GTK_MISC
LIBVIRT_SANDBOX_WIN32
LIBVIRT_SANDBOX_COVERAGE
LIBVIRT_SANDBOX_INTROSPECTION
LIBVIRT_SANDBOX_RPCGEN
AC_OUTPUT(Makefile
......
......@@ -10,78 +10,42 @@ libexec_PROGRAMS = \
libvirt-sandbox-init-lxc \
$(NULL)
PROTOCOL_GENERATOR = libvirt-sandbox-protocol-generator.pl
EXTRA_DIST += $(PROTOCOL_GENERATOR)
sandboxconfigdir = $(sysconfdir)/$(PACKAGE)/scratch
sandboxconfig_DATA = README
lib_LTLIBRARIES = libvirt-sandbox-1.0.la
libvirt_sandbox_init_common_SOURCES = libvirt-sandbox-init-common.c
libvirt_sandbox_init_common_CFLAGS = \
-DLIBEXECDIR="\"$(libexecdir)\"" \
-DSANDBOXCONFIGDIR="\"$(sandboxconfigdir)\"" \
$(COVERAGE_CFLAGS) \
-I$(top_srcdir) \
$(GIO_UNIX_CFLAGS) \
$(LIBVIRT_GLIB_CFLAGS) \
$(LIBVIRT_GOBJECT_CFLAGS) \
$(CAPNG_CFLAGS) \
$(WARN_CFLAGS) \
$(NULL)
libvirt_sandbox_init_common_LDFLAGS = \
-lutil \
$(COVERAGE_CFLAGS:-f%=-Wc,f%) \
$(GIO_UNIX_LIBS) \
$(LIBVIRT_GLIB_LIBS) \
$(LIBVIRT_GOBJECT_LIBS) \
$(CAPNG_LIBS) \
$(WARN_CFLAGS) \
$(NULL)
libvirt_sandbox_init_common_LDADD = \
libvirt-sandbox-1.0.la \
SANDBOX_TEMPLATE_FILES = \
libvirt-sandbox-enum-types.h.template \
libvirt-sandbox-enum-types.c.template \
$(NULL)
libvirt_sandbox_init_lxc_SOURCES = libvirt-sandbox-init-lxc.c
libvirt_sandbox_init_lxc_CFLAGS = \
-DLIBEXECDIR="\"$(libexecdir)\"" \
-DSANDBOXCONFIGDIR="\"$(sandboxconfigdir)\"" \
-I$(top_srcdir) \
$(GIO_UNIX_CFLAGS) \
$(LIBVIRT_GLIB_CFLAGS) \
$(LIBVIRT_GOBJECT_CFLAGS) \
$(WARN_CFLAGS) \
$(NULL)
libvirt_sandbox_init_lxc_LDFLAGS = \
libvirt-sandbox-1.0.la \
$(COVERAGE_CFLAGS:-f%=-Wc,f%) \
$(GIO_UNIX_LIBS) \
$(LIBVIRT_GLIB_LIBS) \
$(LIBVIRT_GOBJECT_LIBS) \
$(WARN_CFLAGS) \
$(NULL)
libvirt_sandbox_init_lxc_LDADD = \
libvirt-sandbox-1.0.la \
SANDBOX_GENERATED_ENUM_FILES = \
libvirt-sandbox-enum-types.h \
libvirt-sandbox-enum-types.c \
$(NULL)
libvirt_sandbox_init_qemu_SOURCES = libvirt-sandbox-init-qemu.c
libvirt_sandbox_init_qemu_CFLAGS = \
-DLIBEXECDIR="\"$(libexecdir)\"" \
-DSANDBOXCONFIGDIR="\"$(sandboxconfigdir)\"" \
$(WARN_CFLAGS) \
$(NULL)
libvirt_sandbox_init_qemu_LDFLAGS = \
-all-static \
$(COVERAGE_CFLAGS:-f%=-Wc,f%) \
$(WARN_CFLAGS) \
SANDBOX_GENERATED_RPC_FILES = \
libvirt-sandbox-protocol.h \
libvirt-sandbox-protocol.c \
$(NULL)
SANDBOX_TEMPLATE_FILES = \
libvirt-sandbox-enum-types.h.template \
libvirt-sandbox-enum-types.c.template \
SANDBOX_PROTOCOL_FILES = \
libvirt-sandbox-protocol.x \
$(NULL)
SANDBOX_GENERATED_FILES = \
libvirt-sandbox-enum-types.h \
libvirt-sandbox-enum-types.c \
$(SANDBOX_GENERATED_ENUM_FILES) \
$(SANDBOX_GENERATED_RPC_FILES) \
$(NULL)
SANDBOX_RPC_FILES = \
libvirt-sandbox-rpcpacket.c \
libvirt-sandbox-rpcpacket.h \
$(NULL)
SANDBOX_HEADER_FILES = \
......@@ -103,6 +67,7 @@ SANDBOX_HEADER_FILES = \
libvirt-sandbox-builder-container.h \
libvirt-sandbox-console.h \
libvirt-sandbox-console-raw.h \
libvirt-sandbox-console-rpc.h \
libvirt-sandbox-context.h \
libvirt-sandbox-context-graphical.h \
libvirt-sandbox-context-interactive.h \
......@@ -126,6 +91,7 @@ SANDBOX_SOURCE_FILES = \
libvirt-sandbox-builder-container.c \
libvirt-sandbox-console.c \
libvirt-sandbox-console-raw.c \
libvirt-sandbox-console-rpc.c \
libvirt-sandbox-context.c \
libvirt-sandbox-context-graphical.c \
libvirt-sandbox-context-interactive.c \
......@@ -136,11 +102,16 @@ libvirt_sandbox_1_0_ladir = $(includedir)/libvirt-sandbox-1.0/libvirt-sandbox
libvirt_sandbox_1_0_la_HEADERS = \
$(SANDBOX_HEADER_FILES)
libvirt_sandbox_1_0_la_SOURCES = \
$(SANDBOX_SOURCE_FILES)
$(SANDBOX_SOURCE_FILES) \
$(SANDBOX_RPC_FILES)
nodist_libvirt_sandbox_1_0_la_HEADERS = \
libvirt-sandbox-enum-types.h
$(NULL)
nodist_libvirt_sandbox_1_0_la_SOURCES = \
libvirt-sandbox-enum-types.c
libvirt-sandbox-enum-types.c \
libvirt-sandbox-protocol.h \
libvirt-sandbox-protocol.c \
$(NULL)
libvirt_sandbox_1_0_la_CFLAGS = \
-DBINDIR="\"$(bindir)\"" \
-DDATADIR="\"$(datadir)\"" \
......@@ -170,7 +141,70 @@ libvirt_sandbox_1_0_la_LDFLAGS = \
-Wl,--version-script=$(srcdir)/libvirt-sandbox.sym \
-version-info $(LIBVIRT_SANDBOX_VERSION_INFO)
EXTRA_DIST += $(SANDBOX_TEMPLATE_FILES)
libvirt_sandbox_init_common_SOURCES = libvirt-sandbox-init-common.c \
$(SANDBOX_GENERATED_RPC_FILES) \
$(SANDBOX_RPC_FILES) \
$(NULL)
libvirt_sandbox_init_common_CFLAGS = \
-DLIBEXECDIR="\"$(libexecdir)\"" \
-DSANDBOXCONFIGDIR="\"$(sandboxconfigdir)\"" \
$(COVERAGE_CFLAGS) \
-I$(top_srcdir) \
$(GIO_UNIX_CFLAGS) \
$(LIBVIRT_GLIB_CFLAGS) \
$(LIBVIRT_GOBJECT_CFLAGS) \
$(CAPNG_CFLAGS) \
$(WARN_CFLAGS) \
$(NULL)
libvirt_sandbox_init_common_LDFLAGS = \
-lutil \
$(COVERAGE_CFLAGS:-f%=-Wc,f%) \
$(GIO_UNIX_LIBS) \
$(LIBVIRT_GLIB_LIBS) \
$(LIBVIRT_GOBJECT_LIBS) \
$(CAPNG_LIBS) \
$(WARN_CFLAGS) \
$(NULL)
libvirt_sandbox_init_common_LDADD = \
libvirt-sandbox-1.0.la \
$(NULL)
libvirt_sandbox_init_lxc_SOURCES = libvirt-sandbox-init-lxc.c
libvirt_sandbox_init_lxc_CFLAGS = \
-DLIBEXECDIR="\"$(libexecdir)\"" \
-DSANDBOXCONFIGDIR="\"$(sandboxconfigdir)\"" \
-I$(top_srcdir) \
$(GIO_UNIX_CFLAGS) \
$(LIBVIRT_GLIB_CFLAGS) \
$(LIBVIRT_GOBJECT_CFLAGS) \
$(WARN_CFLAGS) \
$(NULL)
libvirt_sandbox_init_lxc_LDFLAGS = \
libvirt-sandbox-1.0.la \
$(COVERAGE_CFLAGS:-f%=-Wc,f%) \
$(GIO_UNIX_LIBS) \
$(LIBVIRT_GLIB_LIBS) \
$(LIBVIRT_GOBJECT_LIBS) \
$(WARN_CFLAGS) \
$(NULL)
libvirt_sandbox_init_lxc_LDADD = \
libvirt-sandbox-1.0.la \
$(NULL)
libvirt_sandbox_init_qemu_SOURCES = libvirt-sandbox-init-qemu.c
libvirt_sandbox_init_qemu_CFLAGS = \
-DLIBEXECDIR="\"$(libexecdir)\"" \
-DSANDBOXCONFIGDIR="\"$(sandboxconfigdir)\"" \
$(WARN_CFLAGS) \
$(NULL)
libvirt_sandbox_init_qemu_LDFLAGS = \
-all-static \
$(COVERAGE_CFLAGS:-f%=-Wc,f%) \
$(WARN_CFLAGS) \
$(NULL)
EXTRA_DIST += $(SANDBOX_TEMPLATE_FILES) $(SANDBOX_PROTOCOL_FILES)
BUILT_SOURCES = $(SANDBOX_GENERATED_FILES)
CLEANFILES += $(SANDBOX_GENERATED_FILES)
......@@ -184,6 +218,13 @@ libvirt-sandbox-enum-types.c: $(SANDBOX_HEADER_FILES) libvirt-sandbox-enum-types
sed -e "s/G_TYPE_VIR_CONFIG/GVIR_CONFIG_TYPE/" -e "s/g_vir/gvir/" > libvirt-sandbox-enum-types.c
libvirt-sandbox-protocol.c: $(srcdir)/$(PROTOCOL_GENERATOR) $(SANDBOX_PROTOCOL_FILES)
$(AM_V_GEN)$(PERL) -w $(srcdir)/$(PROTOCOL_GENERATOR) $(RPCGEN) -c $(SANDBOX_PROTOCOL_FILES:%=$(srcdir)/%) $@
libvirt-sandbox-protocol.h: $(srcdir)/$(PROTOCOL_GENERATOR) $(SANDBOX_PROTOCOL_FILES)
$(AM_V_GEN)$(PERL) -w $(srcdir)/$(PROTOCOL_GENERATOR) $(RPCGEN) -h $(SANDBOX_PROTOCOL_FILES:%=$(srcdir)/%) $@
if WITH_INTROSPECTION
LibvirtSandbox-1.0.gir: libvirt-sandbox-1.0.la $(G_IR_SCANNER) Makefile.am
......@@ -206,7 +247,7 @@ LibvirtSandbox-1.0.gir: libvirt-sandbox-1.0.la $(G_IR_SCANNER) Makefile.am
$(srcdir)/libvirt-sandbox.h \
$(SANDBOX_SOURCE_FILES:%=$(srcdir)/%) \
$(SANDBOX_HEADER_FILES:%=$(srcdir)/%) \
$(SANDBOX_GENERATED_FILES:%=%) \
$(SANDBOX_GENERATED_ENUM_FILES:%=%) \
$(NULL)
girdir = $(datadir)/gir-1.0
......
......@@ -302,7 +302,7 @@ static gboolean gvir_sandbox_builder_container_construct_devices(GVirSandboxBuil
g_list_free(networks);
/* The first console is for stdio of the sandboxed app */
/* The first console is for debug messages from stdout/err of the guest init/kernel */
src = gvir_config_domain_chardev_source_pty_new();
con = gvir_config_domain_console_new();
gvir_config_domain_chardev_set_source(GVIR_CONFIG_DOMAIN_CHARDEV(con),
......@@ -324,6 +324,18 @@ static gboolean gvir_sandbox_builder_container_construct_devices(GVirSandboxBuil
g_object_unref(con);
}
if (GVIR_SANDBOX_IS_CONFIG_INTERACTIVE(config)) {
/* The third console is for stdio of the sandboxed app */
src = gvir_config_domain_chardev_source_pty_new();
con = gvir_config_domain_console_new();
gvir_config_domain_chardev_set_source(GVIR_CONFIG_DOMAIN_CHARDEV(con),
GVIR_CONFIG_DOMAIN_CHARDEV_SOURCE(src));
gvir_config_domain_add_device(domain,
GVIR_CONFIG_DOMAIN_DEVICE(con));
g_object_unref(con);
}
if (GVIR_SANDBOX_IS_CONFIG_GRAPHICAL(config)) {
g_set_error(error, GVIR_SANDBOX_BUILDER_CONTAINER_ERROR, 0,
"%s", "Graphical sandboxes are not supported for containers");
......
......@@ -410,7 +410,8 @@ static gboolean gvir_sandbox_builder_machine_construct_devices(GVirSandboxBuilde
GVirConfigDomainInterfaceUser *iface;
GVirConfigDomainMemballoon *ball;
GVirConfigDomainGraphicsSpice *graph;
GVirConfigDomainSerial *con;
GVirConfigDomainConsole *con;
GVirConfigDomainSerial *ser;
GVirConfigDomainChardevSourcePty *src;
GList *tmp = NULL, *mounts = NULL, *networks = NULL;
int i;
......@@ -521,19 +522,41 @@ static gboolean gvir_sandbox_builder_machine_construct_devices(GVirSandboxBuilde
/* The first serial is for stdio of the sandboxed app */
src = gvir_config_domain_chardev_source_pty_new();
con = gvir_config_domain_serial_new();
con = gvir_config_domain_console_new();
gvir_config_domain_console_set_target_type(GVIR_CONFIG_DOMAIN_CONSOLE(con),
GVIR_CONFIG_DOMAIN_CONSOLE_TARGET_SERIAL);
gvir_config_domain_chardev_set_source(GVIR_CONFIG_DOMAIN_CHARDEV(con),
GVIR_CONFIG_DOMAIN_CHARDEV_SOURCE(src));
gvir_config_domain_add_device(domain,
GVIR_CONFIG_DOMAIN_DEVICE(con));
g_object_unref(con);
src = gvir_config_domain_chardev_source_pty_new();
ser = gvir_config_domain_serial_new();
gvir_config_domain_chardev_set_source(GVIR_CONFIG_DOMAIN_CHARDEV(ser),
GVIR_CONFIG_DOMAIN_CHARDEV_SOURCE(src));
gvir_config_domain_add_device(domain,
GVIR_CONFIG_DOMAIN_DEVICE(ser));
g_object_unref(ser);
/* Optional second serial is for a interactive shell (useful for
* troubleshooting stuff */
if (gvir_sandbox_config_get_shell(config)) {
src = gvir_config_domain_chardev_source_pty_new();
con = gvir_config_domain_serial_new();
ser = gvir_config_domain_serial_new();
gvir_config_domain_chardev_set_source(GVIR_CONFIG_DOMAIN_CHARDEV(ser),
GVIR_CONFIG_DOMAIN_CHARDEV_SOURCE(src));
gvir_config_domain_add_device(domain,
GVIR_CONFIG_DOMAIN_DEVICE(ser));
g_object_unref(ser);
}
if (GVIR_SANDBOX_IS_CONFIG_INTERACTIVE(config)) {
src = gvir_config_domain_chardev_source_pty_new();
con = gvir_config_domain_console_new();
gvir_config_domain_console_set_target_type(GVIR_CONFIG_DOMAIN_CONSOLE(con),
GVIR_CONFIG_DOMAIN_CONSOLE_TARGET_VIRTIO);
gvir_config_domain_chardev_set_source(GVIR_CONFIG_DOMAIN_CHARDEV(con),
GVIR_CONFIG_DOMAIN_CHARDEV_SOURCE(src));
gvir_config_domain_add_device(domain,
......@@ -541,7 +564,6 @@ static gboolean gvir_sandbox_builder_machine_construct_devices(GVirSandboxBuilde
g_object_unref(con);
}
if (GVIR_SANDBOX_IS_CONFIG_GRAPHICAL(config)) {
graph = gvir_config_domain_graphics_spice_new();
gvir_config_domain_graphics_spice_set_port(graph, -1);
......
/*
* libvirt-sandbox-console-rpc.c: libvirt sandbox rpc console
*
* Copyright (C) 2011-2012 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#include <config.h>
#include <gio/gfiledescriptorbased.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <libvirt-glib/libvirt-glib-error.h>
#include "libvirt-sandbox/libvirt-sandbox.h"
#include "libvirt-sandbox/libvirt-sandbox-rpcpacket.h"
/**
* SECTION: libvirt-sandbox-console-rpc
* @short_description: A text mode rpc console
* @include: libvirt-sandbox/libvirt-sandbox.h
*
* Provides an object to interface to the text mode console of the sandbox
*
* The GVirSandboxConsole object provides support for interfacing to the
* text mode console of the sandbox. It forwards I/O between the #GVirStream
* associated with the virtual machine's console and a local console
* represented by #GUnixInputStream and #GUnixOutputStream objects.
*
*/
#define GVIR_SANDBOX_CONSOLE_RPC_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), GVIR_SANDBOX_TYPE_CONSOLE_RPC, GVirSandboxConsoleRpcPrivate))
typedef enum {
GVIR_SANDBOX_CONSOLE_RPC_INIT,
GVIR_SANDBOX_CONSOLE_RPC_WAITING,
GVIR_SANDBOX_CONSOLE_RPC_SYNCING,
GVIR_SANDBOX_CONSOLE_RPC_RUNNING,
GVIR_SANDBOX_CONSOLE_RPC_FINISHED,
} GVirSandboxConsoleRpcState;
struct _GVirSandboxConsoleRpcPrivate
{
GVirConnection *connection;
GVirDomain *domain;
GVirStream *console;
gchar *devname;
GUnixInputStream *localStdin;
GUnixOutputStream *localStdout;
GUnixOutputStream *localStderr;
gboolean termiosActive;
struct termios termiosProps;
/* Encoded RPC messages, being sent/received */
GVirSandboxRPCPacket *rx;
GVirSandboxRPCPacket *tx;
/* Decoded RPC message forwarded to stdout */
gchar *localToStdout;
gsize localToStdoutLength;
gsize localToStdoutOffset;
/* Decoded RPC message forwarded to stdout */
gchar *localToStderr;
gsize localToStderrLength;
gsize localToStderrOffset;
GVirSandboxConsoleRpcState state;
/* True if stdin has shown us EOF */
gboolean localEOF;
/* True if we got the EXIT RPC message over console */
gboolean consoleEOF;
GSource *localStdinSource;
GSource *localStdoutSource;
GSource *localStderrSource;
gint consoleWatch;
gsize serial;
};
static void gvir_sandbox_console_rpc_interface_init(gpointer g_iface,
gpointer iface_data);
G_DEFINE_TYPE_EXTENDED(GVirSandboxConsoleRpc, gvir_sandbox_console_rpc, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE(GVIR_SANDBOX_TYPE_CONSOLE,
gvir_sandbox_console_rpc_interface_init));
enum {
PROP_0,
PROP_CONNECTION,
PROP_DOMAIN,
PROP_DEVNAME,
};
enum {
LAST_SIGNAL
};
//static gint signals[LAST_SIGNAL];
#define GVIR_SANDBOX_CONSOLE_RPC_ERROR gvir_sandbox_console_rpc_error_quark()
static GQuark
gvir_sandbox_console_rpc_error_quark(void)
{
return g_quark_from_static_string("gvir-sandbox-console-rpc");
}
static void gvir_sandbox_console_rpc_send_handshake_wait(GVirSandboxConsoleRpc *console)
{
GVirSandboxConsoleRpcPrivate *priv = console->priv;
GVirSandboxRPCPacket *pkt = gvir_sandbox_rpcpacket_new(FALSE);
g_debug("Send wait");
pkt->buffer[0] = GVIR_SANDBOX_PROTOCOL_HANDSHAKE_WAIT;
pkt->bufferLength = 1;
pkt->bufferOffset = 0;
priv->tx = pkt;
}
static void gvir_sandbox_console_rpc_send_handshake_sync(GVirSandboxConsoleRpc *console)
{
GVirSandboxConsoleRpcPrivate *priv = console->priv;
GVirSandboxRPCPacket *pkt = gvir_sandbox_rpcpacket_new(FALSE);
g_debug("Send sync");
pkt->buffer[0] = GVIR_SANDBOX_PROTOCOL_HANDSHAKE_SYNC;
pkt->bufferLength = 1;
pkt->bufferOffset = 0;
priv->tx = pkt;
}
static gboolean gvir_sandbox_console_rpc_send_quit(GVirSandboxConsoleRpc *console,
GError **error)
{
GVirSandboxConsoleRpcPrivate *priv = console->priv;
GVirSandboxRPCPacket *pkt = gvir_sandbox_rpcpacket_new(FALSE);
gboolean ret = FALSE;
g_debug("Send quit");
pkt->header.proc = GVIR_SANDBOX_PROTOCOL_PROC_QUIT;
pkt->header.status = GVIR_SANDBOX_PROTOCOL_STATUS_OK;
pkt->header.type = GVIR_SANDBOX_PROTOCOL_TYPE_DATA;
pkt->header.serial = priv->serial++;
if (!gvir_sandbox_rpcpacket_encode_header(pkt, error))
goto cleanup;
if (!gvir_sandbox_rpcpacket_encode_payload_empty(pkt, error))
goto cleanup;
priv->tx = pkt;
ret = TRUE;
cleanup:
return ret;
}
static gboolean gvir_sandbox_console_rpc_send_stdin(GVirSandboxConsoleRpc *console,
gchar *data,
gsize len,
GError **error)
{
GVirSandboxConsoleRpcPrivate *priv = console->priv;
GVirSandboxRPCPacket *pkt = gvir_sandbox_rpcpacket_new(FALSE);
gboolean ret = FALSE;
g_debug("Send stdin %p %zu", data, len);
pkt->header.proc = GVIR_SANDBOX_PROTOCOL_PROC_STDIN;
pkt->header.status = GVIR_SANDBOX_PROTOCOL_STATUS_OK;
pkt->header.type = GVIR_SANDBOX_PROTOCOL_TYPE_DATA;
pkt->header.serial = priv->serial++;
if (!gvir_sandbox_rpcpacket_encode_header(pkt, error))
goto cleanup;
if (!gvir_sandbox_rpcpacket_encode_payload_raw(pkt, data, len, error))
goto cleanup;
priv->tx = pkt;
ret = TRUE;
cleanup:
if (!ret)
gvir_sandbox_rpcpacket_free(pkt);
return ret;
}
static void gvir_sandbox_console_rpc_get_property(GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GVirSandboxConsoleRpc *console = GVIR_SANDBOX_CONSOLE_RPC(object);
GVirSandboxConsoleRpcPrivate *priv = console->priv;
switch (prop_id) {
case PROP_CONNECTION:
g_value_set_object(value, priv->connection);
break;
case PROP_DOMAIN:
g_value_set_object(value, priv->domain);
break;
case PROP_DEVNAME:
g_value_set_string(value, priv->devname);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
}
}
static void gvir_sandbox_console_rpc_set_property(GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GVirSandboxConsoleRpc *console = GVIR_SANDBOX_CONSOLE_RPC(object);
GVirSandboxConsoleRpcPrivate *priv = console->priv;
switch (prop_id) {
case PROP_CONNECTION:
if (priv->connection)
g_object_unref(priv->connection);
priv->connection = g_value_dup_object(value);
break;
case PROP_DOMAIN:
if (priv->domain)
g_object_unref(priv->domain);
priv->domain = g_value_dup_object(value);
break;
case PROP_DEVNAME:
priv->devname = g_value_dup_string(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
}
}
static void gvir_sandbox_console_rpc_finalize(GObject *object)
{
GVirSandboxConsoleRpc *console = GVIR_SANDBOX_CONSOLE_RPC(object);
GVirSandboxConsoleRpcPrivate *priv = console->priv;
if (priv->localStdin)
gvir_sandbox_console_detach(GVIR_SANDBOX_CONSOLE(console), NULL);
/* All other private fields are free'd by the detach call */
if (priv->domain)
g_object_unref(priv->domain);
if (priv->connection)
g_object_unref(priv->connection);
gvir_sandbox_rpcpacket_free(priv->tx);
gvir_sandbox_rpcpacket_free(priv->rx);
g_free(priv->localToStdout);
g_free(priv->localToStderr);
g_free(priv->devname);
G_OBJECT_CLASS(gvir_sandbox_console_rpc_parent_class)->finalize(object);
}
static void gvir_sandbox_console_rpc_class_init(GVirSandboxConsoleRpcClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
object_class->finalize = gvir_sandbox_console_rpc_finalize;
object_class->get_property = gvir_sandbox_console_rpc_get_property;
object_class->set_property = gvir_sandbox_console_rpc_set_property;
g_object_class_install_property(object_class,
PROP_CONNECTION,
g_param_spec_object("connection",
"Connection",
"The sandbox connection",
GVIR_TYPE_CONNECTION,
G_PARAM_READABLE |
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB));
g_object_class_install_property(object_class,
PROP_DOMAIN,