aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vl.c4
-rw-r--r--vl.h4
-rw-r--r--vnc.c103
3 files changed, 82 insertions, 29 deletions
diff --git a/vl.c b/vl.c
index 9009ce588d..3c8070e346 100644
--- 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 e12b6f3e73..53e822fd97 100644
--- 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 70d30d9d83..f47b5b96b1 100644
--- 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);
}