On 20/10/22 11:16, Laurent Vivier wrote:
Use QIOChannel, QIOChannelSocket and QIONetListener.
This allows net/stream to use all the available parameters provided by
SocketAddress.
Signed-off-by: Laurent Vivier <lviv...@redhat.com>
Acked-by: Michael S. Tsirkin <m...@redhat.com>
---
meson | 2 +-
net/stream.c | 493 +++++++++++++++++-------------------------------
qemu-options.hx | 4 +-
3 files changed, 180 insertions(+), 319 deletions(-)
static int net_stream_server_init(NetClientState *peer,
@@ -283,105 +287,61 @@ static int net_stream_server_init(NetClientState *peer,
{
NetClientState *nc;
NetStreamState *s;
- int fd, ret;
-
- switch (addr->type) {
- case SOCKET_ADDRESS_TYPE_INET: {
- struct sockaddr_in saddr_in;
-
- if (convert_host_port(&saddr_in, addr->u.inet.host, addr->u.inet.port,
- errp) < 0) {
- return -1;
- }
+ QIOChannelSocket *listen_sioc = qio_channel_socket_new();
- fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
- if (fd < 0) {
- error_setg_errno(errp, errno, "can't create stream socket");
- return -1;
- }
- qemu_socket_set_nonblock(fd);
+ nc = qemu_new_net_client(&net_stream_info, peer, model, name);
+ s = DO_UPCAST(NetStreamState, nc, nc);
- socket_set_fast_reuse(fd);
+ s->listen_ioc = QIO_CHANNEL(listen_sioc);
+ qio_channel_socket_listen_async(listen_sioc, addr, 0,
+ net_stream_server_listening, s,
+ NULL, NULL);
- ret = bind(fd, (struct sockaddr *)&saddr_in, sizeof(saddr_in));
- if (ret < 0) {
- error_setg_errno(errp, errno, "can't bind ip=%s to socket",
- inet_ntoa(saddr_in.sin_addr));
- closesocket(fd);
- return -1;
- }
- break;
- }
- case SOCKET_ADDRESS_TYPE_UNIX: {
- struct sockaddr_un saddr_un;
-
- ret = unlink(addr->u.q_unix.path);
- if (ret < 0 && errno != ENOENT) {
- error_setg_errno(errp, errno, "failed to unlink socket %s",
- addr->u.q_unix.path);
- return -1;
- }
+ return 0;
+}
- saddr_un.sun_family = PF_UNIX;
- ret = snprintf(saddr_un.sun_path, sizeof(saddr_un.sun_path), "%s",
- addr->u.q_unix.path);
- if (ret < 0 || ret >= sizeof(saddr_un.sun_path)) {
- error_setg(errp, "UNIX socket path '%s' is too long",
- addr->u.q_unix.path);
- error_append_hint(errp, "Path must be less than %zu bytes\n",
- sizeof(saddr_un.sun_path));
- return -1;
- }
+static void net_stream_client_connected(QIOTask *task, gpointer opaque)
+{
+ NetStreamState *s = opaque;
+ QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(s->ioc);
+ SocketAddress *addr;
+ gchar *uri;
+ int ret;
- fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
- if (fd < 0) {
- error_setg_errno(errp, errno, "can't create stream socket");
- return -1;
- }
- qemu_socket_set_nonblock(fd);
-
- ret = bind(fd, (struct sockaddr *)&saddr_un, sizeof(saddr_un));
- if (ret < 0) {
- error_setg_errno(errp, errno, "can't create socket with path: %s",
- saddr_un.sun_path);
- closesocket(fd);
- return -1;
- }
- break;
- }
- case SOCKET_ADDRESS_TYPE_FD:
- fd = monitor_fd_param(monitor_cur(), addr->u.fd.str, errp);
- if (fd == -1) {
- return -1;
- }
- ret = qemu_socket_try_set_nonblock(fd);
- if (ret < 0) {
- error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
- name, fd);
- return -1;
- }
- break;
- default:
- error_setg(errp, "only support inet or fd type");
- return -1;
+ if (sioc->fd < 0) {
+ qemu_set_info_str(&s->nc, "connection error");
+ goto error;
}
- ret = listen(fd, 0);
- if (ret < 0) {
- error_setg_errno(errp, errno, "can't listen on socket");
- closesocket(fd);
- return -1;
+ addr = qio_channel_socket_get_remote_address(sioc, NULL);
+ g_assert(addr != NULL);
Please use:
addr = qio_channel_socket_get_remote_address(sioc, &error_fatal);
Which is more verbose in case of error, i.e.:
qemu-system-x86_64: socket family 0 unsupported
Instead of:
ERROR:../../net/stream.c:321:net_stream_client_connected: assertion
failed: (addr != NULL)
+ uri = socket_uri(addr);
+ qemu_set_info_str(&s->nc, uri);
+ g_free(uri);
+
+ ret = qemu_socket_try_set_nonblock(sioc->fd);
+ if (addr->type == SOCKET_ADDRESS_TYPE_FD && ret < 0) {
+ qemu_set_info_str(&s->nc, "can't use file descriptor %s (errno %d)",
+ addr->u.fd.str, -ret);
+ qapi_free_SocketAddress(addr);
+ goto error;
}
+ g_assert(ret == 0);
+ qapi_free_SocketAddress(addr);
- nc = qemu_new_net_client(&net_stream_info, peer, model, name);
- s = DO_UPCAST(NetStreamState, nc, nc);
- s->fd = -1;
- s->listen_fd = fd;
- s->nc.link_down = true;
net_socket_rs_init(&s->rs, net_stream_rs_finalize, false);
- qemu_set_fd_handler(s->listen_fd, net_stream_accept, NULL, s);
- return 0;
+ /* Disable Nagle algorithm on TCP sockets to reduce latency */
+ qio_channel_set_delay(s->ioc, false);
+
+ s->ioc_read_tag = qio_channel_add_watch(s->ioc, G_IO_IN, net_stream_send,
+ s, NULL);
+ s->nc.link_down = false;
+
+ return;
+error:
+ object_unref(OBJECT(s->ioc));
+ s->ioc = NULL;
}