Skip to contentSkip to conversation

vnc: support vnc port auto-allocation

PATCH In review Gerd Hoffmann 1 participant 2 messages Oct 24, 2008

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 vnc: support vnc port auto-allocation

Hi folks,

This patch makes qemu (optionally) find a free vnc display, using the -vnc $host:$start,to=$end syntax as discussed on the list a few weeks ago.

cheers,
Gerd

Quoted 1 line

From 5c30379b58500c59d430d3257db65b33326adddf Mon Sep 17 00:00:00 2001

From: Gerd Hoffmann <[email protected]>
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.

---
 vnc.c |   55 +++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 43 insertions(+), 12 deletions(-)
vnc.c +43 -12
index 266460f..9d3c4a3 100644
@@ -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);
Signature · 1 line
1.5.5.1
#1 lore raw

Hi,

Quoted 2 lines

This patch makes qemu (optionally) find a free vnc display, using the -vnc $host:$start,to=$end syntax as discussed on the list a few weeks ago.

While being at it: I'm consider doing something simliar for serial/parallel device tcp redirections. Needs the "info chardev" monitor command patch sent earlier this week to be useful. Probably makes sense to factor out the free tcp port scan then. And when being busy hacking the networking code I'd might just make those bits ipv6 ready along the way.

Comments?

cheers,
Gerd