From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1I2Sks-0008Kg-6H for qemu-devel@nongnu.org; Sun, 24 Jun 2007 10:07:54 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1I2Skr-0008K7-AM for qemu-devel@nongnu.org; Sun, 24 Jun 2007 10:07:53 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1I2Skr-0008Jt-59 for qemu-devel@nongnu.org; Sun, 24 Jun 2007 10:07:53 -0400 Received: from wx-out-0506.google.com ([66.249.82.225]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1I2Skq-0007dG-1a for qemu-devel@nongnu.org; Sun, 24 Jun 2007 10:07:52 -0400 Received: by wx-out-0506.google.com with SMTP id t15so1222750wxc for ; Sun, 24 Jun 2007 07:07:50 -0700 (PDT) Message-ID: <467E7AB0.1000909@codemonkey.ws> Date: Sun, 24 Jun 2007 09:07:44 -0500 From: Anthony Liguori MIME-Version: 1.0 Subject: Re: [Qemu-devel] [PATCH] starting qemu vnc session on a pre-allocated port References: <467E6C25.3010908@codefidence.com> In-Reply-To: <467E6C25.3010908@codefidence.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Shahar Livne wrote: > Hi, > > I am working on a project that runs many concurrent qemu sessions with > vnc. > Handling the vnc ports for the different sessions is an issue that > also project like qemudo tries to solve. > The solution chosen there was to handle a pool of ports and manage > them internally. > Such a solution ignores the fact that these ports may be occupied by > other processes on the same OS, and it actually duplicates an OS task. > A solution that uses external port handling facility (like a native OS > free ports selection), by using a pre-allocated port is suggested. > > Currently there is the following vnc option: > -vnc display [start a VNC server on display] > > Adding the following option: > -vnc-socket sd [force VNC server on an already opened Socket Descriptor] Just redirect each port to a unique unix domain socket and then you can forward traffic to TCP sockets to your heart's content. Regards, Anthony Liguori > 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 */ >