diff options
Diffstat (limited to 'qemu/qga/channel-posix.c')
-rw-r--r-- | qemu/qga/channel-posix.c | 270 |
1 files changed, 0 insertions, 270 deletions
diff --git a/qemu/qga/channel-posix.c b/qemu/qga/channel-posix.c deleted file mode 100644 index 63458c663..000000000 --- a/qemu/qga/channel-posix.c +++ /dev/null @@ -1,270 +0,0 @@ -#include "qemu/osdep.h" -#include <glib.h> -#include <termios.h> -#include "qapi/error.h" -#include "qemu/sockets.h" -#include "qga/channel.h" - -#ifdef CONFIG_SOLARIS -#include <stropts.h> -#endif - -#define GA_CHANNEL_BAUDRATE_DEFAULT B38400 /* for isa-serial channels */ - -struct GAChannel { - GIOChannel *listen_channel; - GIOChannel *client_channel; - GAChannelMethod method; - GAChannelCallback event_cb; - gpointer user_data; -}; - -static int ga_channel_client_add(GAChannel *c, int fd); - -static gboolean ga_channel_listen_accept(GIOChannel *channel, - GIOCondition condition, gpointer data) -{ - GAChannel *c = data; - int ret, client_fd; - bool accepted = false; - struct sockaddr_un addr; - socklen_t addrlen = sizeof(addr); - - g_assert(channel != NULL); - - client_fd = qemu_accept(g_io_channel_unix_get_fd(channel), - (struct sockaddr *)&addr, &addrlen); - if (client_fd == -1) { - g_warning("error converting fd to gsocket: %s", strerror(errno)); - goto out; - } - qemu_set_nonblock(client_fd); - ret = ga_channel_client_add(c, client_fd); - if (ret) { - g_warning("error setting up connection"); - close(client_fd); - goto out; - } - accepted = true; - -out: - /* only accept 1 connection at a time */ - return !accepted; -} - -/* start polling for readable events on listen fd, new==true - * indicates we should use the existing s->listen_channel - */ -static void ga_channel_listen_add(GAChannel *c, int listen_fd, bool create) -{ - if (create) { - c->listen_channel = g_io_channel_unix_new(listen_fd); - } - g_io_add_watch(c->listen_channel, G_IO_IN, ga_channel_listen_accept, c); -} - -static void ga_channel_listen_close(GAChannel *c) -{ - g_assert(c->method == GA_CHANNEL_UNIX_LISTEN); - g_assert(c->listen_channel); - g_io_channel_shutdown(c->listen_channel, true, NULL); - g_io_channel_unref(c->listen_channel); - c->listen_channel = NULL; -} - -/* cleanup state for closed connection/session, start accepting new - * connections if we're in listening mode - */ -static void ga_channel_client_close(GAChannel *c) -{ - g_assert(c->client_channel); - g_io_channel_shutdown(c->client_channel, true, NULL); - g_io_channel_unref(c->client_channel); - c->client_channel = NULL; - if (c->method == GA_CHANNEL_UNIX_LISTEN && c->listen_channel) { - ga_channel_listen_add(c, 0, false); - } -} - -static gboolean ga_channel_client_event(GIOChannel *channel, - GIOCondition condition, gpointer data) -{ - GAChannel *c = data; - gboolean client_cont; - - g_assert(c); - if (c->event_cb) { - client_cont = c->event_cb(condition, c->user_data); - if (!client_cont) { - ga_channel_client_close(c); - return false; - } - } - return true; -} - -static int ga_channel_client_add(GAChannel *c, int fd) -{ - GIOChannel *client_channel; - GError *err = NULL; - - g_assert(c && !c->client_channel); - client_channel = g_io_channel_unix_new(fd); - g_assert(client_channel); - g_io_channel_set_encoding(client_channel, NULL, &err); - if (err != NULL) { - g_warning("error setting channel encoding to binary"); - g_error_free(err); - return -1; - } - g_io_add_watch(client_channel, G_IO_IN | G_IO_HUP, - ga_channel_client_event, c); - c->client_channel = client_channel; - return 0; -} - -static gboolean ga_channel_open(GAChannel *c, const gchar *path, GAChannelMethod method) -{ - int ret; - c->method = method; - - switch (c->method) { - case GA_CHANNEL_VIRTIO_SERIAL: { - int fd = qemu_open(path, O_RDWR | O_NONBLOCK -#ifndef CONFIG_SOLARIS - | O_ASYNC -#endif - ); - if (fd == -1) { - g_critical("error opening channel: %s", strerror(errno)); - return false; - } -#ifdef CONFIG_SOLARIS - ret = ioctl(fd, I_SETSIG, S_OUTPUT | S_INPUT | S_HIPRI); - if (ret == -1) { - g_critical("error setting event mask for channel: %s", - strerror(errno)); - close(fd); - return false; - } -#endif - ret = ga_channel_client_add(c, fd); - if (ret) { - g_critical("error adding channel to main loop"); - close(fd); - return false; - } - break; - } - case GA_CHANNEL_ISA_SERIAL: { - struct termios tio; - int fd = qemu_open(path, O_RDWR | O_NOCTTY | O_NONBLOCK); - if (fd == -1) { - g_critical("error opening channel: %s", strerror(errno)); - return false; - } - tcgetattr(fd, &tio); - /* set up serial port for non-canonical, dumb byte streaming */ - tio.c_iflag &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | - INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY | - IMAXBEL); - tio.c_oflag = 0; - tio.c_lflag = 0; - tio.c_cflag |= GA_CHANNEL_BAUDRATE_DEFAULT; - /* 1 available byte min or reads will block (we'll set non-blocking - * elsewhere, else we have to deal with read()=0 instead) - */ - tio.c_cc[VMIN] = 1; - tio.c_cc[VTIME] = 0; - /* flush everything waiting for read/xmit, it's garbage at this point */ - tcflush(fd, TCIFLUSH); - tcsetattr(fd, TCSANOW, &tio); - ret = ga_channel_client_add(c, fd); - if (ret) { - g_critical("error adding channel to main loop"); - close(fd); - return false; - } - break; - } - case GA_CHANNEL_UNIX_LISTEN: { - Error *local_err = NULL; - int fd = unix_listen(path, NULL, strlen(path), &local_err); - if (local_err != NULL) { - g_critical("%s", error_get_pretty(local_err)); - error_free(local_err); - return false; - } - ga_channel_listen_add(c, fd, true); - break; - } - default: - g_critical("error binding/listening to specified socket"); - return false; - } - - return true; -} - -GIOStatus ga_channel_write_all(GAChannel *c, const gchar *buf, gsize size) -{ - GError *err = NULL; - gsize written = 0; - GIOStatus status = G_IO_STATUS_NORMAL; - - while (size) { - g_debug("sending data, count: %d", (int)size); - status = g_io_channel_write_chars(c->client_channel, buf, size, - &written, &err); - if (status == G_IO_STATUS_NORMAL) { - size -= written; - buf += written; - } else if (status != G_IO_STATUS_AGAIN) { - g_warning("error writing to channel: %s", err->message); - return status; - } - } - - do { - status = g_io_channel_flush(c->client_channel, &err); - } while (status == G_IO_STATUS_AGAIN); - - if (status != G_IO_STATUS_NORMAL) { - g_warning("error flushing channel: %s", err->message); - } - - return status; -} - -GIOStatus ga_channel_read(GAChannel *c, gchar *buf, gsize size, gsize *count) -{ - return g_io_channel_read_chars(c->client_channel, buf, size, count, NULL); -} - -GAChannel *ga_channel_new(GAChannelMethod method, const gchar *path, - GAChannelCallback cb, gpointer opaque) -{ - GAChannel *c = g_new0(GAChannel, 1); - c->event_cb = cb; - c->user_data = opaque; - - if (!ga_channel_open(c, path, method)) { - g_critical("error opening channel"); - ga_channel_free(c); - return NULL; - } - - return c; -} - -void ga_channel_free(GAChannel *c) -{ - if (c->method == GA_CHANNEL_UNIX_LISTEN - && c->listen_channel) { - ga_channel_listen_close(c); - } - if (c->client_channel) { - ga_channel_client_close(c); - } - g_free(c); -} |