static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend, Error **errp) { const char *chardev = qemu_opt_get(opts, "chardev"); ChardevMux *mux; if (chardev == NULL) { error_setg(errp, "chardev: mux: no chardev given"); return; } backend->type = CHARDEV_BACKEND_KIND_MUX; mux = backend->u.mux.data = g_new0(ChardevMux, 1); qemu_chr_parse_common(opts, qapi_ChardevMux_base(mux)); 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); int64_t reconnect = qemu_opt_get_number(opts, "reconnect", 0); const char *path = qemu_opt_get(opts, "path"); const char *host = qemu_opt_get(opts, "host"); const char *port = qemu_opt_get(opts, "port"); const char *tls_creds = qemu_opt_get(opts, "tls-creds"); SocketAddress *addr; ChardevSocket *sock; backend->type = CHARDEV_BACKEND_KIND_SOCKET; if (!path) { if (!host) { error_setg(errp, "chardev: socket: no host given"); return; } if (!port) { error_setg(errp, "chardev: socket: no port given"); return; } } else { if (tls_creds) { error_setg(errp, "TLS can only be used over TCP socket"); return; } } sock = backend->u.socket.data = g_new0(ChardevSocket, 1); qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock)); sock->has_nodelay = true; sock->nodelay = do_nodelay; sock->has_server = true; sock->server = is_listen; sock->has_telnet = true; sock->telnet = is_telnet; sock->has_wait = true; sock->wait = is_waitconnect; sock->has_reconnect = true; sock->reconnect = reconnect; sock->tls_creds = g_strdup(tls_creds); addr = g_new0(SocketAddress, 1); if (path) { UnixSocketAddress *q_unix; addr->type = SOCKET_ADDRESS_KIND_UNIX; q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1); q_unix->path = g_strdup(path); } else { addr->type = SOCKET_ADDRESS_KIND_INET; addr->u.inet.data = g_new(InetSocketAddress, 1); *addr->u.inet.data = (InetSocketAddress) { .host = g_strdup(host), .port = g_strdup(port), .has_to = qemu_opt_get(opts, "to"), .to = qemu_opt_get_number(opts, "to", 0), .has_ipv4 = qemu_opt_get(opts, "ipv4"), .ipv4 = qemu_opt_get_bool(opts, "ipv4", 0), .has_ipv6 = qemu_opt_get(opts, "ipv6"), .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0), }; } sock->addr = addr; } static void char_socket_class_init(ObjectClass *oc, void *data) { ChardevClass *cc = CHARDEV_CLASS(oc); cc->parse = qemu_chr_parse_socket; cc->open = qmp_chardev_open_socket; cc->chr_wait_connected = tcp_chr_wait_connected; cc->chr_write = tcp_chr_write; cc->chr_sync_read = tcp_chr_sync_read; cc->chr_disconnect = tcp_chr_disconnect; cc->get_msgfds = tcp_get_msgfds; cc->set_msgfds = tcp_set_msgfds; cc->chr_add_client = tcp_chr_add_client; cc->chr_add_watch = tcp_chr_add_watch; cc->chr_update_read_handler = tcp_chr_update_read_handler; }
static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend, Error **errp) { const char *host = qemu_opt_get(opts, "host"); const char *port = qemu_opt_get(opts, "port"); const char *localaddr = qemu_opt_get(opts, "localaddr"); const char *localport = qemu_opt_get(opts, "localport"); bool has_local = false; SocketAddressLegacy *addr; ChardevUdp *udp; backend->type = CHARDEV_BACKEND_KIND_UDP; if (host == NULL || strlen(host) == 0) { host = "localhost"; } if (port == NULL || strlen(port) == 0) { error_setg(errp, "chardev: udp: remote port not specified"); return; } if (localport == NULL || strlen(localport) == 0) { localport = "0"; } else { has_local = true; } if (localaddr == NULL || strlen(localaddr) == 0) { localaddr = ""; } else { has_local = true; } udp = backend->u.udp.data = g_new0(ChardevUdp, 1); qemu_chr_parse_common(opts, qapi_ChardevUdp_base(udp)); addr = g_new0(SocketAddressLegacy, 1); addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET; addr->u.inet.data = g_new(InetSocketAddress, 1); *addr->u.inet.data = (InetSocketAddress) { .host = g_strdup(host), .port = g_strdup(port), .has_ipv4 = qemu_opt_get(opts, "ipv4"), .ipv4 = qemu_opt_get_bool(opts, "ipv4", 0), .has_ipv6 = qemu_opt_get(opts, "ipv6"), .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0), }; udp->remote = addr; if (has_local) { udp->has_local = true; addr = g_new0(SocketAddressLegacy, 1); addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET; addr->u.inet.data = g_new(InetSocketAddress, 1); *addr->u.inet.data = (InetSocketAddress) { .host = g_strdup(localaddr), .port = g_strdup(localport), }; udp->local = addr; } } static void qmp_chardev_open_udp(Chardev *chr, ChardevBackend *backend, bool *be_opened, Error **errp) { ChardevUdp *udp = backend->u.udp.data; SocketAddress *local_addr = socket_address_flatten(udp->local); SocketAddress *remote_addr = socket_address_flatten(udp->remote); QIOChannelSocket *sioc = qio_channel_socket_new(); char *name; UdpChardev *s = UDP_CHARDEV(chr); int ret; ret = qio_channel_socket_dgram_sync(sioc, local_addr, remote_addr, errp); qapi_free_SocketAddress(local_addr); qapi_free_SocketAddress(remote_addr); if (ret < 0) { object_unref(OBJECT(sioc)); return; } name = g_strdup_printf("chardev-udp-%s", chr->label); qio_channel_set_name(QIO_CHANNEL(sioc), name); g_free(name); s->ioc = QIO_CHANNEL(sioc); /* be isn't opened until we get a connection */ *be_opened = false; }
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 is_tn3270 = qemu_opt_get_bool(opts, "tn3270", false); bool do_nodelay = !qemu_opt_get_bool(opts, "delay", true); int64_t reconnect = qemu_opt_get_number(opts, "reconnect", 0); const char *path = qemu_opt_get(opts, "path"); const char *host = qemu_opt_get(opts, "host"); const char *port = qemu_opt_get(opts, "port"); const char *tls_creds = qemu_opt_get(opts, "tls-creds"); SocketAddressLegacy *addr; ChardevSocket *sock; backend->type = CHARDEV_BACKEND_KIND_SOCKET; if (!path) { if (!host) { error_setg(errp, "chardev: socket: no host given"); return; } if (!port) { error_setg(errp, "chardev: socket: no port given"); return; } } else { if (tls_creds) { error_setg(errp, "TLS can only be used over TCP socket"); return; } } sock = backend->u.socket.data = g_new0(ChardevSocket, 1); qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock)); sock->has_nodelay = true; sock->nodelay = do_nodelay; sock->has_server = true; sock->server = is_listen; sock->has_telnet = true; sock->telnet = is_telnet; sock->has_tn3270 = true; sock->tn3270 = is_tn3270; sock->has_wait = true; sock->wait = is_waitconnect; sock->has_reconnect = true; sock->reconnect = reconnect; sock->tls_creds = g_strdup(tls_creds); addr = g_new0(SocketAddressLegacy, 1); if (path) { UnixSocketAddress *q_unix; addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX; q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1); q_unix->path = g_strdup(path); } else { addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET; addr->u.inet.data = g_new(InetSocketAddress, 1); *addr->u.inet.data = (InetSocketAddress) { .host = g_strdup(host), .port = g_strdup(port), .has_to = qemu_opt_get(opts, "to"), .to = qemu_opt_get_number(opts, "to", 0), .has_ipv4 = qemu_opt_get(opts, "ipv4"), .ipv4 = qemu_opt_get_bool(opts, "ipv4", 0), .has_ipv6 = qemu_opt_get(opts, "ipv6"), .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0), }; } sock->addr = addr; } static void char_socket_get_addr(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { SocketChardev *s = SOCKET_CHARDEV(obj); visit_type_SocketAddress(v, name, &s->addr, errp); }