From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KvtR9-0004FS-On for qemu-devel@nongnu.org; Fri, 31 Oct 2008 08:49:12 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KvtR7-0004Ch-AA for qemu-devel@nongnu.org; Fri, 31 Oct 2008 08:49:10 -0400 Received: from [199.232.76.173] (port=56577 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KvtR7-0004CK-5J for qemu-devel@nongnu.org; Fri, 31 Oct 2008 08:49:09 -0400 Received: from mx2.redhat.com ([66.187.237.31]:47791) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1KvtR5-0001lZ-SO for qemu-devel@nongnu.org; Fri, 31 Oct 2008 08:49:08 -0400 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id m9VCn4AE007720 for ; Fri, 31 Oct 2008 08:49:04 -0400 From: Gerd Hoffmann Date: Fri, 31 Oct 2008 13:47:34 +0100 Message-Id: <1225457254-1000-5-git-send-email-kraxel@redhat.com> In-Reply-To: <1225457254-1000-1-git-send-email-kraxel@redhat.com> References: <1225457254-1000-1-git-send-email-kraxel@redhat.com> Subject: [Qemu-devel] [PATCH 4/4] sockets: switch over tcp/telnet/unix serial line to new helper functions. Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Gerd Hoffmann This switches the tcp, telnet and unix socket support for character devices (serial/parallel, ...) to the new socket helpers. Thereby they gain IPv6 support and also get ability to search for a free tcp port. Syntax is the same as for vnc, using a to= option, like this: -serial tcp:localhost:5000,to=5099,server This will check the 5000 -> 5099 port range (inclusive) for a free tcp port. Likewise you can get auto-allocated unix sockets by specifying an empty path: -serial unix:,server qemu will create a randomly named socket in $TMPDIR then. You can use the "info chardev" command added by the first patch in this series to figure the tcp port / unix socket actually allocated. Signed-off-by: Gerd Hoffmann --- vl.c | 131 +++++++++++++++++------------------------------------------------- 1 files changed, 33 insertions(+), 98 deletions(-) diff --git a/vl.c b/vl.c index e4648f9..b6c61be 100644 --- a/vl.c +++ b/vl.c @@ -3370,9 +3370,6 @@ static void udp_chr_update_read_handler(CharDriverState *chr) } } -#ifndef _WIN32 -static int parse_unix_path(struct sockaddr_un *uaddr, const char *str); -#endif int parse_host_src_port(struct sockaddr_in *haddr, struct sockaddr_in *saddr, const char *str); @@ -3629,32 +3626,11 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, { CharDriverState *chr = NULL; TCPCharDriver *s = NULL; - int fd = -1, ret, err, val; + int fd = -1, offset = 0; int is_listen = 0; int is_waitconnect = 1; int do_nodelay = 0; const char *ptr; - struct sockaddr_in saddr; -#ifndef _WIN32 - struct sockaddr_un uaddr; -#endif - struct sockaddr *addr; - socklen_t addrlen; - -#ifndef _WIN32 - if (is_unix) { - addr = (struct sockaddr *)&uaddr; - addrlen = sizeof(uaddr); - if (parse_unix_path(&uaddr, host_str) < 0) - goto fail; - } else -#endif - { - addr = (struct sockaddr *)&saddr; - addrlen = sizeof(saddr); - if (parse_host_port(&saddr, host_str) < 0) - goto fail; - } ptr = host_str; while((ptr = strchr(ptr,','))) { @@ -3665,6 +3641,8 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, is_waitconnect = 0; } else if (!strncmp(ptr,"nodelay",6)) { do_nodelay = 1; + } else if (!strncmp(ptr,"to=",3)) { + /* nothing, inet_listen() parses this one */; } else { printf("Unknown option: %s\n", ptr); goto fail; @@ -3680,13 +3658,31 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, if (!s) goto fail; -#ifndef _WIN32 - if (is_unix) - fd = socket(PF_UNIX, SOCK_STREAM, 0); - else -#endif - fd = socket(PF_INET, SOCK_STREAM, 0); - + if (is_listen) { + chr->filename = qemu_malloc(256); + if (is_unix) { + strcpy(chr->filename, "unix:"); + } else if (is_telnet) { + strcpy(chr->filename, "telnet:"); + } else { + strcpy(chr->filename, "tcp:"); + } + offset = strlen(chr->filename); + } + if (is_unix) { + if (is_listen) { + fd = unix_listen(host_str, chr->filename + offset, 256 - offset); + } else { + fd = unix_connect(host_str); + } + } else { + if (is_listen) { + fd = inet_listen(host_str, chr->filename + offset, 256 - offset, + SOCK_STREAM, 0); + } else { + fd = inet_connect(host_str, SOCK_STREAM); + } + } if (fd < 0) goto fail; @@ -3704,61 +3700,20 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, chr->chr_close = tcp_chr_close; if (is_listen) { - /* allow fast reuse */ -#ifndef _WIN32 - if (is_unix) { - char path[109]; - pstrcpy(path, sizeof(path), uaddr.sun_path); - unlink(path); - } else -#endif - { - val = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); - } - - ret = bind(fd, addr, addrlen); - if (ret < 0) - goto fail; - - ret = listen(fd, 0); - if (ret < 0) - goto fail; - s->listen_fd = fd; qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr); if (is_telnet) s->do_telnetopt = 1; } else { - for(;;) { - ret = connect(fd, addr, addrlen); - if (ret < 0) { - err = socket_error(); - if (err == EINTR || err == EWOULDBLOCK) { - } else if (err == EINPROGRESS) { - break; -#ifdef _WIN32 - } else if (err == WSAEALREADY) { - break; -#endif - } else { - goto fail; - } - } else { - s->connected = 1; - break; - } - } + s->connected = 1; s->fd = fd; socket_set_nodelay(fd); - if (s->connected) - tcp_chr_connect(chr); - else - qemu_set_fd_handler(s->fd, NULL, tcp_chr_connect, chr); + tcp_chr_connect(chr); } if (is_listen && is_waitconnect) { - printf("QEMU waiting for connection on: %s\n", host_str); + printf("QEMU waiting for connection on: %s\n", + chr->filename ? chr->filename : host_str); tcp_chr_accept(chr); socket_set_nonblock(s->listen_fd); } @@ -4035,26 +3990,6 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str) return 0; } -#ifndef _WIN32 -static int parse_unix_path(struct sockaddr_un *uaddr, const char *str) -{ - const char *p; - int len; - - len = MIN(108, strlen(str)); - p = strchr(str, ','); - if (p) - len = MIN(len, p - str); - - memset(uaddr, 0, sizeof(*uaddr)); - - uaddr->sun_family = AF_UNIX; - memcpy(uaddr->sun_path, str, len); - - return 0; -} -#endif - /* find or alloc a new VLAN */ VLANState *qemu_find_vlan(int id) { @@ -8284,7 +8219,7 @@ static void help(int exitcode) "-ipv4 Use IPv4 only.\n" "-ipv6 Use UPv6 only.\n" " By default qemu uses what is available on your machine.\n" - " Applies to -vnc.\n" + " Applies to -vnc and -serial tcp.\n" "\n" "Linux boot specific:\n" "-kernel bzImage use 'bzImage' as kernel image\n" -- 1.5.6.5