From 71cab5ca0d9f10cf9f07eaf3033687bf85459d52 Mon Sep 17 00:00:00 2001 From: ths Date: Sat, 25 Aug 2007 01:35:38 +0000 Subject: [PATCH] Refactor VNC server setup API, by Daniel P. Berrange. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3133 c046a42c-6fe2-441c-8c8c-71466251a162 --- vl.c | 4 ++- vl.h | 4 ++- vnc.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++----------------- 3 files changed, 82 insertions(+), 29 deletions(-) diff --git a/vl.c b/vl.c index 9009ce5..3c8070e 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 e12b6f3..53e822f 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 70d30d9..f47b5b9 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); } -- 1.7.9.5