Index: qemu-doc.texi =================================================================== RCS file: /sources/qemu/qemu/qemu-doc.texi,v retrieving revision 1.179 diff -u -r1.179 qemu-doc.texi --- qemu-doc.texi 14 Jan 2008 22:09:11 -0000 1.179 +++ qemu-doc.texi 16 Jan 2008 07:25:30 -0000 @@ -429,10 +429,16 @@ Connections will be allowed over UNIX domain sockets where @var{path} is the location of a unix socket to listen for connections on. +@item @var{rev}:@var{interface}:@var{port} + +Makes a reverse connection to a VNC viewer listening on +@var{interface} on port @var{port}. Optionally, @var{interface} can be +omitted in which case QEMU will connect to @var{port} on the local machine. + @item none -VNC is initialized by not started. The monitor @code{change} command can be used -to later start the VNC server. +VNC is initialized but not started. The monitor @code{change} command +can be used to later start the VNC server. @end table Index: vnc.c =================================================================== RCS file: /sources/qemu/qemu/vnc.c,v retrieving revision 1.33 diff -u -r1.33 vnc.c --- vnc.c 14 Jan 2008 21:45:55 -0000 1.33 +++ vnc.c 16 Jan 2008 07:25:30 -0000 @@ -1898,6 +1898,22 @@ return 0; } +static void vnc_connect(VncState *vs) +{ + VNC_DEBUG("New client on socket %d\n", vs->csock); + socket_set_nonblock(vs->csock); + qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs); + vnc_write(vs, "RFB 003.008\n", 12); + vnc_flush(vs); + vnc_read_when(vs, protocol_version, 12); + memset(vs->old_data, 0, vs->ds->linesize * vs->ds->height); + memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row)); + vs->has_resize = 0; + vs->has_hextile = 0; + vs->ds->dpy_copy = NULL; + vnc_update_client(vs); +} + static void vnc_listen_read(void *opaque) { VncState *vs = opaque; @@ -1909,18 +1925,7 @@ vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen); if (vs->csock != -1) { - VNC_DEBUG("New client on socket %d\n", vs->csock); - socket_set_nonblock(vs->csock); - qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque); - vnc_write(vs, "RFB 003.008\n", 12); - vnc_flush(vs); - vnc_read_when(vs, protocol_version, 12); - memset(vs->old_data, 0, vs->ds->linesize * vs->ds->height); - memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row)); - vs->has_resize = 0; - vs->has_hextile = 0; - vs->ds->dpy_copy = NULL; - vnc_update_client(vs); + vnc_connect(vs); } } @@ -2087,6 +2092,7 @@ VncState *vs = ds ? (VncState *)ds->opaque : vnc_state; const char *options; int password = 0; + int reverse = 0; #if CONFIG_VNC_TLS int tls = 0, x509 = 0; #endif @@ -2179,6 +2185,13 @@ } #endif } + if (strstart(display, "rev:", &p)) { + reverse = 1; + display = p; + if (!strchr(display, ':')) { + display = p - 1; + } + } #ifndef _WIN32 if (strstart(display, "unix:", &p)) { addr = (struct sockaddr *)&uaddr; @@ -2196,7 +2209,9 @@ memset(uaddr.sun_path, 0, 108); snprintf(uaddr.sun_path, 108, "%s", p); - unlink(uaddr.sun_path); + if (!reverse) { + unlink(uaddr.sun_path); + } } else #endif { @@ -2210,7 +2225,7 @@ return -1; } - iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900); + iaddr.sin_port = htons(ntohs(iaddr.sin_port) + (reverse ? 0 : 5900)); vs->lsock = socket(PF_INET, SOCK_STREAM, 0); if (vs->lsock == -1) { @@ -2233,6 +2248,22 @@ } } + if (reverse) { + if (connect(vs->lsock, addr, addrlen) == -1) { + fprintf(stderr, "Connection to VNC client failed\n"); + close(vs->lsock); + vs->lsock = -1; + free(vs->display); + vs->display = NULL; + return -1; + } else { + vs->csock = vs->lsock; + vs->lsock = -1; + vnc_connect(vs); + return 0; + } + } + if (bind(vs->lsock, addr, addrlen) == -1) { fprintf(stderr, "bind() failed\n"); close(vs->lsock);