>From 5c30379b58500c59d430d3257db65b33326adddf Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 24 Oct 2008 10:36:20 +0200 Subject: [PATCH] vnc: support vnc port auto-allocation. This patch adds support for automatically allocating an unused vnc display port. It adds a to= option for vnc, specifying the upper limit for the display number to try. Scanning is started at the display number given in the display specification, i.e. this command line: -vnc localhost:7,to=11 will try displays 7 to 11 (inclusive). The display actually allocated can be queried using the "info vnc" monitor command. Signed-off-by: Gerd Hoffmann --- vnc.c | 55 +++++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 43 insertions(+), 12 deletions(-) diff --git a/vnc.c b/vnc.c index 266460f..9d3c4a3 100644 --- a/vnc.c +++ b/vnc.c @@ -2303,16 +2303,16 @@ int vnc_display_open(DisplayState *ds, const char *display) const char *options; int password = 0; int reverse = 0; + int to_port = 0; #ifdef CONFIG_VNC_TLS int tls = 0, x509 = 0; #endif vnc_display_close(ds); - if (strcmp(display, "none") == 0) - return 0; - if (!(vs->display = strdup(display))) return -1; + if (strcmp(display, "none") == 0) + return 0; options = display; while ((options = strchr(options, ','))) { @@ -2321,6 +2321,8 @@ int vnc_display_open(DisplayState *ds, const char *display) password = 1; /* Require password auth */ } else if (strncmp(options, "reverse", 7) == 0) { reverse = 1; + } else if (strncmp(options, "to=", 3) == 0) { + to_port = atoi(options+3) + 5900; #ifdef CONFIG_VNC_TLS } else if (strncmp(options, "tls", 3) == 0) { tls = 1; /* Require TLS */ @@ -2416,6 +2418,14 @@ int vnc_display_open(DisplayState *ds, const char *display) if (!reverse) { unlink(uaddr.sun_path); + if (bind(vs->lsock, addr, addrlen) == -1) { + fprintf(stderr, "bind() failed\n"); + close(vs->lsock); + vs->lsock = -1; + free(vs->display); + vs->display = NULL; + return -1; + } } } else #endif @@ -2451,6 +2461,36 @@ int vnc_display_open(DisplayState *ds, const char *display) vs->display = NULL; return -1; } + + if (!reverse) { + if (to_port < 5900) + to_port = ntohs(iaddr.sin_port); + while (ntohs(iaddr.sin_port) <= to_port) { + if (bind(vs->lsock, addr, addrlen) == 0) + break; + iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 1); + } + if (ntohs(iaddr.sin_port) <= to_port) { + /* success: set vs->display so "info vnc" displays the actual port */ + char *dpy, *opts, *h; + opts = strchr(vs->display,','); + h = strchr(vs->display, ':'); + if (h) + *h = 0; + dpy = qemu_malloc(256); + snprintf(dpy, 256, "%s:%d%s", h ? vs->display : "", + ntohs(iaddr.sin_port) - 5900, opts); + qemu_free(vs->display); + vs->display = dpy; + } else { + fprintf(stderr, "didn't find free vnc display port\n"); + close(vs->lsock); + vs->lsock = -1; + free(vs->display); + vs->display = NULL; + return -1; + } + } } if (reverse) { @@ -2469,15 +2509,6 @@ int vnc_display_open(DisplayState *ds, const char *display) } } - if (bind(vs->lsock, addr, addrlen) == -1) { - fprintf(stderr, "bind() failed\n"); - close(vs->lsock); - vs->lsock = -1; - free(vs->display); - vs->display = NULL; - return -1; - } - if (listen(vs->lsock, 1) == -1) { fprintf(stderr, "listen() failed\n"); close(vs->lsock); -- 1.5.5.1