Run monitor over unix domain sockets, by Anthony Liguori.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2259 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
1cb6c3fd38
commit
ffd843bcdc
@ -586,6 +586,11 @@ MAGIC_SYSRQ sequence if you use a telnet that supports sending the break
|
||||
sequence. Typically in unix telnet you do it with Control-] and then
|
||||
type "send break" followed by pressing the enter key.
|
||||
|
||||
@item unix:path[,server][,nowait]
|
||||
A unix domain socket is used instead of a tcp socket. The option works the
|
||||
same as if you had specified @code{-serial tcp} except the unix domain socket
|
||||
@var{path} is used for connections.
|
||||
|
||||
@end table
|
||||
|
||||
@item -parallel dev
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#define socket_error() errno
|
||||
#define closesocket(s) close(s)
|
||||
|
115
vl.c
115
vl.c
@ -2206,6 +2206,7 @@ static void udp_chr_add_read_handler(CharDriverState *chr,
|
||||
}
|
||||
|
||||
int parse_host_port(struct sockaddr_in *saddr, const char *str);
|
||||
int parse_unix_path(struct sockaddr_un *uaddr, const char *str);
|
||||
int parse_host_src_port(struct sockaddr_in *haddr,
|
||||
struct sockaddr_in *saddr,
|
||||
const char *str);
|
||||
@ -2270,6 +2271,7 @@ typedef struct {
|
||||
int connected;
|
||||
int max_size;
|
||||
int do_telnetopt;
|
||||
int is_unix;
|
||||
} TCPCharDriver;
|
||||
|
||||
static void tcp_chr_accept(void *opaque);
|
||||
@ -2291,6 +2293,8 @@ static int tcp_chr_read_poll(void *opaque)
|
||||
TCPCharDriver *s = chr->opaque;
|
||||
if (!s->connected)
|
||||
return 0;
|
||||
if (!s->fd_can_read)
|
||||
return 0;
|
||||
s->max_size = s->fd_can_read(s->fd_opaque);
|
||||
return s->max_size;
|
||||
}
|
||||
@ -2416,12 +2420,25 @@ static void tcp_chr_accept(void *opaque)
|
||||
CharDriverState *chr = opaque;
|
||||
TCPCharDriver *s = chr->opaque;
|
||||
struct sockaddr_in saddr;
|
||||
#ifndef _WIN32
|
||||
struct sockaddr_un uaddr;
|
||||
#endif
|
||||
struct sockaddr *addr;
|
||||
socklen_t len;
|
||||
int fd;
|
||||
|
||||
for(;;) {
|
||||
len = sizeof(saddr);
|
||||
fd = accept(s->listen_fd, (struct sockaddr *)&saddr, &len);
|
||||
#ifndef _WIN32
|
||||
if (s->is_unix) {
|
||||
len = sizeof(uaddr);
|
||||
addr = (struct sockaddr *)&uaddr;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
len = sizeof(saddr);
|
||||
addr = (struct sockaddr *)&saddr;
|
||||
}
|
||||
fd = accept(s->listen_fd, addr, &len);
|
||||
if (fd < 0 && errno != EINTR) {
|
||||
return;
|
||||
} else if (fd >= 0) {
|
||||
@ -2447,7 +2464,8 @@ static void tcp_chr_close(CharDriverState *chr)
|
||||
}
|
||||
|
||||
static CharDriverState *qemu_chr_open_tcp(const char *host_str,
|
||||
int is_telnet)
|
||||
int is_telnet,
|
||||
int is_unix)
|
||||
{
|
||||
CharDriverState *chr = NULL;
|
||||
TCPCharDriver *s = NULL;
|
||||
@ -2456,9 +2474,26 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
|
||||
int is_waitconnect = 1;
|
||||
const char *ptr;
|
||||
struct sockaddr_in saddr;
|
||||
#ifndef _WIN32
|
||||
struct sockaddr_un uaddr;
|
||||
#endif
|
||||
struct sockaddr *addr;
|
||||
socklen_t addrlen;
|
||||
|
||||
if (parse_host_port(&saddr, host_str) < 0)
|
||||
goto fail;
|
||||
#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,','))) {
|
||||
@ -2481,8 +2516,14 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
|
||||
s = qemu_mallocz(sizeof(TCPCharDriver));
|
||||
if (!s)
|
||||
goto fail;
|
||||
|
||||
fd = socket(PF_INET, SOCK_STREAM, 0);
|
||||
|
||||
#ifndef _WIN32
|
||||
if (is_unix)
|
||||
fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
else
|
||||
#endif
|
||||
fd = socket(PF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (fd < 0)
|
||||
goto fail;
|
||||
|
||||
@ -2492,24 +2533,43 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
|
||||
s->connected = 0;
|
||||
s->fd = -1;
|
||||
s->listen_fd = -1;
|
||||
s->is_unix = is_unix;
|
||||
|
||||
chr->opaque = s;
|
||||
chr->chr_write = tcp_chr_write;
|
||||
chr->chr_add_read_handler = tcp_chr_add_read_handler;
|
||||
chr->chr_close = tcp_chr_close;
|
||||
|
||||
if (is_listen) {
|
||||
/* allow fast reuse */
|
||||
val = 1;
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
|
||||
#ifndef _WIN32
|
||||
if (is_unix) {
|
||||
char path[109];
|
||||
strncpy(path, uaddr.sun_path, 108);
|
||||
path[108] = 0;
|
||||
unlink(path);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
val = 1;
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
|
||||
}
|
||||
|
||||
ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
|
||||
if (ret < 0)
|
||||
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, (struct sockaddr *)&saddr, sizeof(saddr));
|
||||
ret = connect(fd, addr, addrlen);
|
||||
if (ret < 0) {
|
||||
err = socket_error();
|
||||
if (err == EINTR || err == EWOULDBLOCK) {
|
||||
@ -2530,10 +2590,6 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
|
||||
qemu_set_fd_handler(s->fd, NULL, tcp_chr_connect, chr);
|
||||
}
|
||||
|
||||
chr->opaque = s;
|
||||
chr->chr_write = tcp_chr_write;
|
||||
chr->chr_add_read_handler = tcp_chr_add_read_handler;
|
||||
chr->chr_close = tcp_chr_close;
|
||||
if (is_listen && is_waitconnect) {
|
||||
printf("QEMU waiting for connection on: %s\n", host_str);
|
||||
tcp_chr_accept(chr);
|
||||
@ -2559,16 +2615,18 @@ CharDriverState *qemu_chr_open(const char *filename)
|
||||
return qemu_chr_open_null();
|
||||
} else
|
||||
if (strstart(filename, "tcp:", &p)) {
|
||||
return qemu_chr_open_tcp(p, 0);
|
||||
return qemu_chr_open_tcp(p, 0, 0);
|
||||
} else
|
||||
if (strstart(filename, "telnet:", &p)) {
|
||||
return qemu_chr_open_tcp(p, 1);
|
||||
return qemu_chr_open_tcp(p, 1, 0);
|
||||
} else
|
||||
if (strstart(filename, "udp:", &p)) {
|
||||
return qemu_chr_open_udp(p);
|
||||
} else
|
||||
#ifndef _WIN32
|
||||
if (strstart(filename, "file:", &p)) {
|
||||
if (strstart(filename, "unix:", &p)) {
|
||||
return qemu_chr_open_tcp(p, 0, 1);
|
||||
} else if (strstart(filename, "file:", &p)) {
|
||||
return qemu_chr_open_file_out(p);
|
||||
} else if (strstart(filename, "pipe:", &p)) {
|
||||
return qemu_chr_open_pipe(p);
|
||||
@ -2743,6 +2801,24 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str)
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* find or alloc a new VLAN */
|
||||
VLANState *qemu_find_vlan(int id)
|
||||
{
|
||||
@ -6955,6 +7031,7 @@ int main(int argc, char **argv)
|
||||
vm_start();
|
||||
}
|
||||
}
|
||||
|
||||
main_loop();
|
||||
quit_timers();
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user