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.
Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- qemu-sockets.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-tool.c | 6 ++++ qemu_socket.h | 4 +++ 3 file modificati, 109 inserzioni(+) diff --git a/qemu-sockets.c b/qemu-sockets.c index 778428f..d3bc712 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 */ @@ -714,6 +715,104 @@ int unix_connect(const char *path, Error **errp) #endif +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, bool block, bool *in_progress, Error **errp) +{ + QemuOpts *opts; + int fd; + + if (in_progress) { + *in_progress = false; + } + + 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, block, in_progress, errp); + break; + + case SOCKET_ADDRESS_KIND_UNIX: + qemu_opt_set(opts, "path", addr->q_unix->path); + fd = unix_connect_opts(opts, block, in_progress, 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; +} + +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 18205ba..7658fde 100644 --- a/qemu-tool.c +++ b/qemu-tool.c @@ -42,6 +42,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 37dcafd..9cd99f2 100644 --- a/qemu_socket.h +++ b/qemu_socket.h @@ -52,6 +52,10 @@ int unix_listen(const char *path, char *ostr, int olen, Error **errp); int unix_connect_opts(QemuOpts *opts, bool block, bool *in_progress, Error **errp); int unix_connect(const char *path, Error **errp); +SocketAddress *socket_parse(const char *str, Error **errp); +int socket_connect(SocketAddress *addr, bool block, bool *in_progress, Error **errp); +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