overrides the new socket opening for the vnc on 5900+display port, and
uses the given sd socket descriptor instead.
In this way, one can create a socket, bind it to any specific port
(e.g. arbitrary free port given by the OS), and only then start the
qemu with the socket descriptor. Doing this, all the ports accounting
is done by the OS.
The patch is against cvs 2007-06-21, but I think nothing relevant has
changed since.
Comments are welcome,
Shahar
------------------------------------------------------------------------
Index: vnc.c
===================================================================
--- vnc.c (revision 6)
+++ vnc.c (revision 8)
@@ -59,6 +59,7 @@
QEMUTimer *timer;
int lsock;
int csock;
+ int fsock;
DisplayState *ds;
int need_update;
int width;
@@ -99,9 +100,14 @@
if (vnc_state == NULL)
term_printf("VNC server disabled\n");
else {
- term_printf("VNC server active on: ");
- term_print_filename(vnc_state->display);
- term_printf("\n");
+ if (vnc_state->fsock == -1) {
+ term_printf("VNC server active on: ");
+ term_print_filename(vnc_state->display);
+ term_printf("\n");
+ } else {
+ term_printf("VNC server active on socket descriptor: %d",
vnc_state->fsock);
+ term_printf("\n");
+ }
if (vnc_state->csock == -1)
term_printf("No client connected\n");
@@ -1169,7 +1175,7 @@
extern int parse_host_port(struct sockaddr_in *saddr, const char *str);
-void vnc_display_init(DisplayState *ds, const char *arg)
+void vnc_display_init(DisplayState *ds, const char *arg, int forced_vnc_socket)
{
struct sockaddr *addr;
struct sockaddr_in iaddr;
@@ -1191,6 +1197,7 @@
vs->lsock = -1;
vs->csock = -1;
+ vs->fsock = forced_vnc_socket;
vs->depth = 4;
vs->last_x = -1;
vs->last_y = -1;
@@ -1213,60 +1220,67 @@
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
+ if (vs->fsock == -1) {
+#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);
- }
- }
-
- if (bind(vs->lsock, addr, addrlen) == -1) {
- fprintf(stderr, "bind() failed\n");
- exit(1);
- }
+ {
+ 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);
+ }
+ }
+
+ if (bind(vs->lsock, addr, addrlen) == -1) {
+ fprintf(stderr, "bind() failed\n");
+ exit(1);
+ }
+
+ if (listen(vs->lsock, 1) == -1) {
+ fprintf(stderr, "listen() failed\n");
+ exit(1);
+ }
- if (listen(vs->lsock, 1) == -1) {
- fprintf(stderr, "listen() failed\n");
- exit(1);
+ } else {
+ vs->lsock = vs->fsock;
+ fprintf(stdout, "using forced socket %d\n",vs->fsock);
}
-
+
ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
if (ret == -1) {
exit(1);
Index: vl.c
===================================================================
--- vl.c (revision 6)
+++ vl.c (revision 8)
@@ -178,6 +178,7 @@
static VLANState *first_vlan;
int smp_cpus = 1;
const char *vnc_display;
+int vnc_socket = -1;
#if defined(TARGET_SPARC)
#define MAX_CPUS 16
#elif defined(TARGET_I386)
@@ -6651,6 +6652,7 @@
"-no-reboot exit instead of rebooting\n"
"-loadvm file start right away with a saved state (loadvm in
monitor)\n"
"-vnc display start a VNC server on display\n"
+ "-vnc-socket sd force VNC server on an already opened Socket
Descriptor\n"
#ifndef _WIN32
"-daemonize daemonize QEMU after initializing\n"
#endif
@@ -6745,6 +6747,7 @@
QEMU_OPTION_usbdevice,
QEMU_OPTION_smp,
QEMU_OPTION_vnc,
+ QEMU_OPTION_vnc_socket,
QEMU_OPTION_no_acpi,
QEMU_OPTION_no_reboot,
QEMU_OPTION_show_cursor,
@@ -6836,6 +6839,7 @@
{ "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
{ "smp", HAS_ARG, QEMU_OPTION_smp },
{ "vnc", HAS_ARG, QEMU_OPTION_vnc },
+ { "vnc-socket", HAS_ARG, QEMU_OPTION_vnc_socket },
/* temporary options */
{ "usb", 0, QEMU_OPTION_usb },
@@ -7588,6 +7592,18 @@
case QEMU_OPTION_vnc:
vnc_display = optarg;
break;
+ case QEMU_OPTION_vnc_socket:
+ {
+ int sd;
+ sd = atoi(optarg);
+ if (sd < 0) {
+ fprintf(stderr, "Bad argument to vnc socket
descriptor\n");
+ exit(1);
+ } else {
+ vnc_socket = sd;
+ }
+ break;
+ }
case QEMU_OPTION_no_acpi:
acpi_enabled = 0;
break;
@@ -7879,7 +7895,7 @@
if (nographic) {
/* nothing to do */
} else if (vnc_display != NULL) {
- vnc_display_init(ds, vnc_display);
+ vnc_display_init(ds, vnc_display, vnc_socket);
} else {
#if defined(CONFIG_SDL)
sdl_display_init(ds, full_screen, no_frame);
Index: vl.h
===================================================================
--- vl.h (revision 6)
+++ vl.h (revision 8)
@@ -965,7 +965,7 @@
void cocoa_display_init(DisplayState *ds, int full_screen);
/* vnc.c */
-void vnc_display_init(DisplayState *ds, const char *display);
+void vnc_display_init(DisplayState *ds, const char *display, int
forced_vnc_socket);
void do_info_vnc(void);
/* x_keymap.c */