Refactor VNC server setup API, by Daniel P. Berrange.
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 25 Aug 2007 01:35:38 +0000 (01:35 +0000)
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 25 Aug 2007 01:35:38 +0000 (01:35 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3133 c046a42c-6fe2-441c-8c8c-71466251a162

vl.c
vl.h
vnc.c

diff --git a/vl.c b/vl.c
index 9009ce5..3c8070e 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -8319,7 +8319,9 @@ int main(int argc, char **argv)
         /* nearly nothing to do */
         dumb_display_init(ds);
     } else if (vnc_display != NULL) {
-        vnc_display_init(ds, vnc_display);
+        vnc_display_init(ds);
+        if (vnc_display_open(ds, vnc_display) < 0)
+            exit(1);
     } else {
 #if defined(CONFIG_SDL)
         sdl_display_init(ds, full_screen, no_frame);
diff --git a/vl.h b/vl.h
index e12b6f3..53e822f 100644 (file)
--- a/vl.h
+++ b/vl.h
@@ -967,7 +967,9 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame);
 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);
+void vnc_display_close(DisplayState *ds);
+int vnc_display_open(DisplayState *ds, const char *display);
 void do_info_vnc(void);
 
 /* x_keymap.c */
diff --git a/vnc.c b/vnc.c
index 70d30d9..f47b5b9 100644 (file)
--- a/vnc.c
+++ b/vnc.c
@@ -73,7 +73,7 @@ struct VncState
     int last_x;
     int last_y;
 
-    const char *display;
+    char *display;
 
     Buffer output;
     Buffer input;
@@ -1169,16 +1169,8 @@ static void vnc_listen_read(void *opaque)
 
 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)
 {
-    struct sockaddr *addr;
-    struct sockaddr_in iaddr;
-#ifndef _WIN32
-    struct sockaddr_un uaddr;
-#endif
-    int reuse_addr, ret;
-    socklen_t addrlen;
-    const char *p;
     VncState *vs;
 
     vs = qemu_mallocz(sizeof(VncState));
@@ -1187,7 +1179,7 @@ void vnc_display_init(DisplayState *ds, const char *arg)
 
     ds->opaque = vs;
     vnc_state = vs;
-    vs->display = arg;
+    vs->display = NULL;
 
     vs->lsock = -1;
     vs->csock = -1;
@@ -1212,7 +1204,49 @@ void vnc_display_init(DisplayState *ds, const char *arg)
     memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
 
     vnc_dpy_resize(vs->ds, 640, 400);
+}
+
+void vnc_display_close(DisplayState *ds)
+{
+    VncState *vs = (VncState *)ds->opaque;
+
+    if (vs->display) {
+       qemu_free(vs->display);
+       vs->display = NULL;
+    }
+    if (vs->lsock != -1) {
+       qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL);
+       close(vs->lsock);
+       vs->lsock = -1;
+    }
+    if (vs->csock != -1) {
+       qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
+       closesocket(vs->csock);
+       vs->csock = -1;
+       buffer_reset(&vs->input);
+       buffer_reset(&vs->output);
+       vs->need_update = 0;
+    }
+}
+
+int vnc_display_open(DisplayState *ds, const char *arg)
+{
+    struct sockaddr *addr;
+    struct sockaddr_in iaddr;
+#ifndef _WIN32
+    struct sockaddr_un uaddr;
+#endif
+    int reuse_addr, ret;
+    socklen_t addrlen;
+    const char *p;
+    VncState *vs = (VncState *)ds->opaque;
+
+    vnc_display_close(ds);
+    if (strcmp(arg, "none") == 0)
+       return 0;
 
+    if (!(vs->display = strdup(arg)))
+       return -1;
 #ifndef _WIN32
     if (strstart(arg, "unix:", &p)) {
        addr = (struct sockaddr *)&uaddr;
@@ -1221,7 +1255,9 @@ void vnc_display_init(DisplayState *ds, const char *arg)
        vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0);
        if (vs->lsock == -1) {
            fprintf(stderr, "Could not create socket\n");
-           exit(1);
+           free(vs->display);
+           vs->display = NULL;
+           return -1;
        }
 
        uaddr.sun_family = AF_UNIX;
@@ -1235,40 +1271,53 @@ void vnc_display_init(DisplayState *ds, const char *arg)
        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);
+           free(vs->display);
+           vs->display = NULL;
+           return -1;
        }
-           
+
        iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);
 
+       vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
+       if (vs->lsock == -1) {
+           fprintf(stderr, "Could not create socket\n");
+           free(vs->display);
+           vs->display = NULL;
+           return -1;
+       }
+
        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);
+           close(vs->lsock);
+           vs->lsock = -1;
+           free(vs->display);
+           vs->display = NULL;
+           return -1;
        }
     }
 
     if (bind(vs->lsock, addr, addrlen) == -1) {
        fprintf(stderr, "bind() failed\n");
-       exit(1);
+       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");
-       exit(1);
+       close(vs->lsock);
+       vs->lsock = -1;
+       free(vs->display);
+       vs->display = NULL;
+       return -1;
     }
 
-    ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
-    if (ret == -1) {
-       exit(1);
-    }
+    return qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
 }