Unix domain socket support for VNC, by Anthony Liguori.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2260 c046a42c-6fe2-441c-8c8c-71466251a162
master
ths 2006-12-22 02:09:07 +00:00
parent ffd843bcdc
commit 73fc97427b
4 changed files with 76 additions and 39 deletions

View File

@ -247,14 +247,21 @@ command line application. The emulated serial port is redirected on
the console. Therefore, you can still use QEMU to debug a Linux kernel the console. Therefore, you can still use QEMU to debug a Linux kernel
with a serial console. with a serial console.
@item -vnc d @item -vnc display
Normally, QEMU uses SDL to display the VGA output. With this option, Normally, QEMU uses SDL to display the VGA output. With this option,
you can have QEMU listen on VNC display @var{d} and redirect the VGA you can have QEMU listen on VNC display @var{display} and redirect the VGA
display over the VNC session. It is very useful to enable the usb display over the VNC session. It is very useful to enable the usb
tablet device when using this option (option @option{-usbdevice tablet device when using this option (option @option{-usbdevice
tablet}). When using the VNC display, you must use the @option{-k} tablet}). When using the VNC display, you must use the @option{-k}
option to set the keyboard layout. option to set the keyboard layout if you are not using en-us.
@var{display} may be in the form @var{interface:d}, in which case connections
will only be allowed from @var{interface} on display @var{d}. Optionally,
@var{interface} can be omitted. @var{display} can also be in the form
@var{unix:path} where @var{path} is the location of a unix socket to listen for
connections on.
@item -k language @item -k language

10
vl.c
View File

@ -152,7 +152,7 @@ int win2k_install_hack = 0;
int usb_enabled = 0; int usb_enabled = 0;
static VLANState *first_vlan; static VLANState *first_vlan;
int smp_cpus = 1; int smp_cpus = 1;
int vnc_display = -1; const char *vnc_display;
#if defined(TARGET_SPARC) #if defined(TARGET_SPARC)
#define MAX_CPUS 16 #define MAX_CPUS 16
#elif defined(TARGET_I386) #elif defined(TARGET_I386)
@ -6818,11 +6818,7 @@ int main(int argc, char **argv)
} }
break; break;
case QEMU_OPTION_vnc: case QEMU_OPTION_vnc:
vnc_display = atoi(optarg); vnc_display = optarg;
if (vnc_display < 0) {
fprintf(stderr, "Invalid VNC display\n");
exit(1);
}
break; break;
case QEMU_OPTION_no_acpi: case QEMU_OPTION_no_acpi:
acpi_enabled = 0; acpi_enabled = 0;
@ -6946,7 +6942,7 @@ int main(int argc, char **argv)
/* terminal init */ /* terminal init */
if (nographic) { if (nographic) {
dumb_display_init(ds); dumb_display_init(ds);
} else if (vnc_display != -1) { } else if (vnc_display != NULL) {
vnc_display_init(ds, vnc_display); vnc_display_init(ds, vnc_display);
} else { } else {
#if defined(CONFIG_SDL) #if defined(CONFIG_SDL)

2
vl.h
View File

@ -867,7 +867,7 @@ void sdl_display_init(DisplayState *ds, int full_screen);
void cocoa_display_init(DisplayState *ds, int full_screen); void cocoa_display_init(DisplayState *ds, int full_screen);
/* vnc.c */ /* vnc.c */
void vnc_display_init(DisplayState *ds, int display); void vnc_display_init(DisplayState *ds, const char *display);
/* ide.c */ /* ide.c */
#define MAX_DISKS 4 #define MAX_DISKS 4

90
vnc.c
View File

@ -1101,10 +1101,18 @@ static void vnc_listen_read(void *opaque)
} }
} }
void vnc_display_init(DisplayState *ds, int display) extern int parse_host_port(struct sockaddr_in *saddr, const char *str);
void vnc_display_init(DisplayState *ds, const char *arg)
{ {
struct sockaddr_in addr; struct sockaddr *addr;
struct sockaddr_in iaddr;
#ifndef _WIN32
struct sockaddr_un uaddr;
#endif
int reuse_addr, ret; int reuse_addr, ret;
socklen_t addrlen;
const char *p;
VncState *vs; VncState *vs;
vs = qemu_mallocz(sizeof(VncState)); vs = qemu_mallocz(sizeof(VncState));
@ -1126,25 +1134,60 @@ void vnc_display_init(DisplayState *ds, int display)
if (!vs->kbd_layout) if (!vs->kbd_layout)
exit(1); exit(1);
vs->lsock = socket(PF_INET, SOCK_STREAM, 0); vs->ds->data = NULL;
if (vs->lsock == -1) { vs->ds->dpy_update = vnc_dpy_update;
fprintf(stderr, "Could not create socket\n"); vs->ds->dpy_resize = vnc_dpy_resize;
exit(1); vs->ds->dpy_refresh = vnc_dpy_refresh;
memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
vnc_dpy_resize(vs->ds, 640, 400);
#ifndef _WIN32
if (strstart(arg, "unix:", &p)) {
addr = (struct sockaddr *)&uaddr;
addrlen = sizeof(uaddr);
vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0);
if (vs->lsock == -1) {
fprintf(stderr, "Could not create socket\n");
exit(1);
}
uaddr.sun_family = AF_UNIX;
memset(uaddr.sun_path, 0, 108);
snprintf(uaddr.sun_path, 108, "%s", p);
unlink(uaddr.sun_path);
} else
#endif
{
addr = (struct sockaddr *)&iaddr;
addrlen = sizeof(iaddr);
vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
if (vs->lsock == -1) {
fprintf(stderr, "Could not create socket\n");
exit(1);
}
if (parse_host_port(&iaddr, arg) < 0) {
fprintf(stderr, "Could not parse VNC address\n");
exit(1);
}
iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);
reuse_addr = 1;
ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
(const char *)&reuse_addr, sizeof(reuse_addr));
if (ret == -1) {
fprintf(stderr, "setsockopt() failed\n");
exit(1);
}
} }
addr.sin_family = AF_INET; if (bind(vs->lsock, addr, addrlen) == -1) {
addr.sin_port = htons(5900 + display);
memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
reuse_addr = 1;
ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
(const char *)&reuse_addr, sizeof(reuse_addr));
if (ret == -1) {
fprintf(stderr, "setsockopt() failed\n");
exit(1);
}
if (bind(vs->lsock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
fprintf(stderr, "bind() failed\n"); fprintf(stderr, "bind() failed\n");
exit(1); exit(1);
} }
@ -1158,13 +1201,4 @@ void vnc_display_init(DisplayState *ds, int display)
if (ret == -1) { if (ret == -1) {
exit(1); exit(1);
} }
vs->ds->data = NULL;
vs->ds->dpy_update = vnc_dpy_update;
vs->ds->dpy_resize = vnc_dpy_resize;
vs->ds->dpy_refresh = vnc_dpy_refresh;
memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
vnc_dpy_resize(vs->ds, 640, 400);
} }