These are QAPI-friendly versions of the qemu-sockets functions. They support IP sockets, Unix sockets, and named file descriptors, using a QAPI union to dispatch to the correct function.
Reviewed-by: Luiz Capitulino <lcapitul...@redhat.com> Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- Makefile | 2 +- qemu-sockets.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-tool.c | 6 ++++ qemu_socket.h | 5 +++ 4 file modificati, 111 inserzioni(+). 1 rimozione(-) diff --git a/Makefile b/Makefile index a9c22bf..b8b1f3c 100644 --- a/Makefile +++ b/Makefile @@ -159,7 +159,7 @@ qemu-img.o: qemu-img-cmds.h tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \ qemu-timer-common.o main-loop.o notify.o \ - iohandler.o cutils.o iov.o async.o + iohandler.o cutils.o iov.o async.o error.o tools-obj-$(CONFIG_POSIX) += compatfd.o qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y) $(qapi-obj-y) \ diff --git a/qemu-sockets.c b/qemu-sockets.c index 5946962..e8d0a3c 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -22,6 +22,7 @@ #include <errno.h> #include <unistd.h> +#include "monitor.h" #include "qemu_socket.h" #include "qemu-common.h" /* for qemu_isdigit */ #include "main-loop.h" @@ -845,6 +846,104 @@ int unix_nonblocking_connect(const char *path, return sock; } +SocketAddress *socket_parse(const char *str, Error **errp) +{ + SocketAddress *addr = NULL; + + addr = g_new(SocketAddress, 1); + if (strstart(str, "unix:", NULL)) { + if (str[5] == '\0') { + error_setg(errp, "invalid Unix socket address\n"); + goto fail; + } else { + addr->kind = SOCKET_ADDRESS_KIND_UNIX; + addr->q_unix = g_new(UnixSocketAddress, 1); + addr->q_unix->path = g_strdup(str + 5); + } + } else if (strstart(str, "fd:", NULL)) { + if (str[3] == '\0') { + error_setg(errp, "invalid file descriptor address\n"); + goto fail; + } else { + addr->kind = SOCKET_ADDRESS_KIND_FD; + addr->fd = g_new(String, 1); + addr->fd->str = g_strdup(str + 3); + } + } else { + addr->kind = SOCKET_ADDRESS_KIND_INET; + addr->inet = g_new(IPSocketAddress, 1); + addr->inet = inet_parse(str, errp); + if (addr->inet == NULL) { + goto fail; + } + } + return addr; + +fail: + qapi_free_SocketAddress(addr); + return NULL; +} + +int socket_connect(SocketAddress *addr, Error **errp, + NonBlockingConnectHandler *callback, void *opaque) +{ + QemuOpts *opts; + int fd; + + opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); + switch (addr->kind) { + case SOCKET_ADDRESS_KIND_INET: + inet_addr_to_opts(opts, addr->inet); + fd = inet_connect_opts(opts, errp, callback, opaque); + break; + + case SOCKET_ADDRESS_KIND_UNIX: + qemu_opt_set(opts, "path", addr->q_unix->path); + fd = unix_connect_opts(opts, errp, callback, opaque); + break; + + case SOCKET_ADDRESS_KIND_FD: + fd = monitor_get_fd(cur_mon, addr->fd->str, errp); + if (callback) { + callback(fd, opaque); + } + break; + + default: + abort(); + } + qemu_opts_del(opts); + return fd; +} + +int socket_listen(SocketAddress *addr, Error **errp) +{ + QemuOpts *opts; + int fd; + + opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); + switch (addr->kind) { + case SOCKET_ADDRESS_KIND_INET: + inet_addr_to_opts(opts, addr->inet); + fd = inet_listen_opts(opts, 0, errp); + break; + + case SOCKET_ADDRESS_KIND_UNIX: + qemu_opt_set(opts, "path", addr->q_unix->path); + fd = unix_listen_opts(opts, errp); + break; + + case SOCKET_ADDRESS_KIND_FD: + fd = monitor_get_fd(cur_mon, addr->fd->str, errp); + break; + + default: + abort(); + } + qemu_opts_del(opts); + return fd; +} + #ifdef _WIN32 static void socket_cleanup(void) { diff --git a/qemu-tool.c b/qemu-tool.c index f2f9813..6fe1dd2 100644 --- a/qemu-tool.c +++ b/qemu-tool.c @@ -48,6 +48,12 @@ int monitor_cur_is_qmp(void) return 0; } +int monitor_get_fd(Monitor *mon, const char *name, Error **errp) +{ + error_setg(errp, "only QEMU supports file descriptor passing"); + return -1; +} + void monitor_set_error(Monitor *mon, QError *qerror) { } diff --git a/qemu_socket.h b/qemu_socket.h index 89a5feb..02490ad 100644 --- a/qemu_socket.h +++ b/qemu_socket.h @@ -65,6 +65,11 @@ int unix_nonblocking_connect(const char *str, NonBlockingConnectHandler *callback, void *opaque, Error **errp); +SocketAddress *socket_parse(const char *str, Error **errp); +int socket_connect(SocketAddress *addr, Error **errp, + NonBlockingConnectHandler *callback, void *opaque); +int socket_listen(SocketAddress *addr, Error **errp); + /* Old, ipv4 only bits. Don't use for new code. */ int parse_host_port(struct sockaddr_in *saddr, const char *str); int socket_init(void); -- 1.7.12.1