aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-06-20 20:47:54 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-06-23 10:42:41 +0100
commitf1cfb27291b22bbc3611711ff9e763c74d93c25c (patch)
treef8cac825601b0ece2be7ffbe076e7465f000af61
parentb75925224cec2f083958ee10ffaddf875ed53c16 (diff)
qemu-char: Convert socket char backend to parse/kind
Convert the socket char backend to the new style QAPI framework; this allows it to return an Error ** to callers who might not want it to print directly about socket failures. [The rationale for this patch from the ranchu perspective is that it means that if our attempt to create the android console backend chardev fails because the port was in use we don't get a spurious warning printed to stderr.] Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--qemu-char.c114
1 files changed, 58 insertions, 56 deletions
diff --git a/qemu-char.c b/qemu-char.c
index 17b476edf0..22ba162ff7 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2704,61 +2704,6 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
return chr;
}
-static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
-{
- CharDriverState *chr = NULL;
- Error *local_err = NULL;
- int fd = -1;
-
- bool is_listen = qemu_opt_get_bool(opts, "server", false);
- bool is_waitconnect = is_listen && qemu_opt_get_bool(opts, "wait", true);
- bool is_telnet = qemu_opt_get_bool(opts, "telnet", false);
- bool do_nodelay = !qemu_opt_get_bool(opts, "delay", true);
- bool is_unix = qemu_opt_get(opts, "path") != NULL;
-
- if (is_unix) {
- if (is_listen) {
- fd = unix_listen_opts(opts, &local_err);
- } else {
- fd = unix_connect_opts(opts, &local_err, NULL, NULL);
- }
- } else {
- if (is_listen) {
- fd = inet_listen_opts(opts, 0, &local_err);
- } else {
- fd = inet_connect_opts(opts, &local_err, NULL, NULL);
- }
- }
- if (fd < 0) {
- goto fail;
- }
-
- if (!is_waitconnect)
- qemu_set_nonblock(fd);
-
- chr = qemu_chr_open_socket_fd(fd, do_nodelay, is_listen, is_telnet,
- is_waitconnect, &local_err);
- if (local_err) {
- goto fail;
- }
- return chr;
-
-
- fail:
- if (local_err) {
- qerror_report_err(local_err);
- error_free(local_err);
- }
- if (fd >= 0) {
- closesocket(fd);
- }
- if (chr) {
- g_free(chr->opaque);
- g_free(chr);
- }
- return NULL;
-}
-
/*********************************************************/
/* Ring buffer chardev */
@@ -3165,6 +3110,62 @@ static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend,
backend->mux->chardev = g_strdup(chardev);
}
+static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
+ Error **errp)
+{
+ bool is_listen = qemu_opt_get_bool(opts, "server", false);
+ bool is_waitconnect = is_listen && qemu_opt_get_bool(opts, "wait", true);
+ bool is_telnet = qemu_opt_get_bool(opts, "telnet", false);
+ bool do_nodelay = !qemu_opt_get_bool(opts, "delay", true);
+ const char *path = qemu_opt_get(opts, "path");
+ const char *host = qemu_opt_get(opts, "host");
+ const char *port = qemu_opt_get(opts, "port");
+ SocketAddress *addr;
+
+ if (!path) {
+ if (!host) {
+ error_setg(errp, "chardev: socket: no host given");
+ return;
+ }
+ if (!port) {
+ error_setg(errp, "chardev: socket: no port given");
+ return;
+ }
+ }
+
+ backend->socket = g_new0(ChardevSocket, 1);
+
+ backend->socket->has_nodelay = true;
+ backend->socket->nodelay = do_nodelay;
+ backend->socket->has_server = true;
+ backend->socket->server = is_listen;
+ backend->socket->has_telnet = true;
+ backend->socket->telnet = is_telnet;
+ backend->socket->has_wait = true;
+ backend->socket->wait = is_waitconnect;
+
+ addr = g_new0(SocketAddress, 1);
+ if (path) {
+ addr->kind = SOCKET_ADDRESS_KIND_UNIX;
+ addr->q_unix = g_new0(UnixSocketAddress, 1);
+ addr->q_unix->path = g_strdup(path);
+ } else {
+ addr->kind = SOCKET_ADDRESS_KIND_INET;
+ addr->inet = g_new0(InetSocketAddress, 1);
+ addr->inet->host = g_strdup(host);
+ addr->inet->port = g_strdup(port);
+ addr->inet->to = qemu_opt_get_number(opts, "to", 0);
+ addr->inet->has_to = true;
+ if (qemu_opt_get_bool(opts, "ipv4", 0)) {
+ addr->inet->has_ipv4 = addr->inet->ipv4 = true;
+ }
+ if (qemu_opt_get_bool(opts, "ipv6", 0)) {
+ addr->inet->has_ipv6 = addr->inet->ipv6 = true;
+ }
+ }
+ backend->socket->addr = addr;
+}
+
typedef struct CharDriver {
const char *name;
/* old, pre qapi */
@@ -3845,7 +3846,8 @@ void qmp_chardev_remove(const char *id, Error **errp)
static void register_types(void)
{
register_char_driver_qapi("null", CHARDEV_BACKEND_KIND_NULL, NULL);
- register_char_driver("socket", qemu_chr_open_socket);
+ register_char_driver_qapi("socket", CHARDEV_BACKEND_KIND_SOCKET,
+ qemu_chr_parse_socket);
register_char_driver("udp", qemu_chr_open_udp);
register_char_driver_qapi("ringbuf", CHARDEV_BACKEND_KIND_RINGBUF,
qemu_chr_parse_ringbuf);