[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 4/4] sockets: switch over tcp/telnet/unix serial lin
From: |
Gerd Hoffmann |
Subject: |
[Qemu-devel] [PATCH 4/4] sockets: switch over tcp/telnet/unix serial line to new helper functions. |
Date: |
Tue, 28 Oct 2008 13:55:18 +0100 |
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 <address@hidden>
---
vl.c | 129 ++++++++++++++++-------------------------------------------------
1 files changed, 32 insertions(+), 97 deletions(-)
diff --git a/vl.c b/vl.c
index 2112585..7d45c7f 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)
{
--
1.5.6.5
[Qemu-devel] [PATCH 4/4] sockets: switch over tcp/telnet/unix serial line to new helper functions.,
Gerd Hoffmann <=
[Qemu-devel] [PATCH 2/4] sockets: helper functions for qemu., Gerd Hoffmann, 2008/10/28
[Qemu-devel] [PATCH 3/4] sockets: switch vnc to new code, support vnc port auto-allocation., Gerd Hoffmann, 2008/10/28
Re: [Qemu-devel] [PATCH 0/4] ipv6 and autoport patches., Anthony Liguori, 2008/10/28