diff options
Diffstat (limited to 'vnc.c')
-rw-r--r-- | vnc.c | 103 |
1 files changed, 76 insertions, 27 deletions
@@ -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); } |