Commit 73fc97427b6410b9ebd38b8d88831be050ce189b
1 parent
ffd843bc
Unix domain socket support for VNC, by Anthony Liguori.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2260 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
74 additions
and
37 deletions
qemu-doc.texi
... | ... | @@ -247,14 +247,21 @@ command line application. The emulated serial port is redirected on |
247 | 247 | the console. Therefore, you can still use QEMU to debug a Linux kernel |
248 | 248 | with a serial console. |
249 | 249 | |
250 | -@item -vnc d | |
250 | +@item -vnc display | |
251 | 251 | |
252 | 252 | Normally, QEMU uses SDL to display the VGA output. With this option, |
253 | -you can have QEMU listen on VNC display @var{d} and redirect the VGA | |
253 | +you can have QEMU listen on VNC display @var{display} and redirect the VGA | |
254 | 254 | display over the VNC session. It is very useful to enable the usb |
255 | 255 | tablet device when using this option (option @option{-usbdevice |
256 | 256 | tablet}). When using the VNC display, you must use the @option{-k} |
257 | -option to set the keyboard layout. | |
257 | +option to set the keyboard layout if you are not using en-us. | |
258 | + | |
259 | +@var{display} may be in the form @var{interface:d}, in which case connections | |
260 | +will only be allowed from @var{interface} on display @var{d}. Optionally, | |
261 | +@var{interface} can be omitted. @var{display} can also be in the form | |
262 | +@var{unix:path} where @var{path} is the location of a unix socket to listen for | |
263 | +connections on. | |
264 | + | |
258 | 265 | |
259 | 266 | @item -k language |
260 | 267 | ... | ... |
vl.c
... | ... | @@ -152,7 +152,7 @@ int win2k_install_hack = 0; |
152 | 152 | int usb_enabled = 0; |
153 | 153 | static VLANState *first_vlan; |
154 | 154 | int smp_cpus = 1; |
155 | -int vnc_display = -1; | |
155 | +const char *vnc_display; | |
156 | 156 | #if defined(TARGET_SPARC) |
157 | 157 | #define MAX_CPUS 16 |
158 | 158 | #elif defined(TARGET_I386) |
... | ... | @@ -6818,11 +6818,7 @@ int main(int argc, char **argv) |
6818 | 6818 | } |
6819 | 6819 | break; |
6820 | 6820 | case QEMU_OPTION_vnc: |
6821 | - vnc_display = atoi(optarg); | |
6822 | - if (vnc_display < 0) { | |
6823 | - fprintf(stderr, "Invalid VNC display\n"); | |
6824 | - exit(1); | |
6825 | - } | |
6821 | + vnc_display = optarg; | |
6826 | 6822 | break; |
6827 | 6823 | case QEMU_OPTION_no_acpi: |
6828 | 6824 | acpi_enabled = 0; |
... | ... | @@ -6946,7 +6942,7 @@ int main(int argc, char **argv) |
6946 | 6942 | /* terminal init */ |
6947 | 6943 | if (nographic) { |
6948 | 6944 | dumb_display_init(ds); |
6949 | - } else if (vnc_display != -1) { | |
6945 | + } else if (vnc_display != NULL) { | |
6950 | 6946 | vnc_display_init(ds, vnc_display); |
6951 | 6947 | } else { |
6952 | 6948 | #if defined(CONFIG_SDL) | ... | ... |
vl.h
... | ... | @@ -867,7 +867,7 @@ void sdl_display_init(DisplayState *ds, int full_screen); |
867 | 867 | void cocoa_display_init(DisplayState *ds, int full_screen); |
868 | 868 | |
869 | 869 | /* vnc.c */ |
870 | -void vnc_display_init(DisplayState *ds, int display); | |
870 | +void vnc_display_init(DisplayState *ds, const char *display); | |
871 | 871 | |
872 | 872 | /* ide.c */ |
873 | 873 | #define MAX_DISKS 4 | ... | ... |
vnc.c
... | ... | @@ -1101,10 +1101,18 @@ static void vnc_listen_read(void *opaque) |
1101 | 1101 | } |
1102 | 1102 | } |
1103 | 1103 | |
1104 | -void vnc_display_init(DisplayState *ds, int display) | |
1104 | +extern int parse_host_port(struct sockaddr_in *saddr, const char *str); | |
1105 | + | |
1106 | +void vnc_display_init(DisplayState *ds, const char *arg) | |
1105 | 1107 | { |
1106 | - struct sockaddr_in addr; | |
1108 | + struct sockaddr *addr; | |
1109 | + struct sockaddr_in iaddr; | |
1110 | +#ifndef _WIN32 | |
1111 | + struct sockaddr_un uaddr; | |
1112 | +#endif | |
1107 | 1113 | int reuse_addr, ret; |
1114 | + socklen_t addrlen; | |
1115 | + const char *p; | |
1108 | 1116 | VncState *vs; |
1109 | 1117 | |
1110 | 1118 | vs = qemu_mallocz(sizeof(VncState)); |
... | ... | @@ -1126,25 +1134,60 @@ void vnc_display_init(DisplayState *ds, int display) |
1126 | 1134 | if (!vs->kbd_layout) |
1127 | 1135 | exit(1); |
1128 | 1136 | |
1129 | - vs->lsock = socket(PF_INET, SOCK_STREAM, 0); | |
1130 | - if (vs->lsock == -1) { | |
1131 | - fprintf(stderr, "Could not create socket\n"); | |
1132 | - exit(1); | |
1133 | - } | |
1137 | + vs->ds->data = NULL; | |
1138 | + vs->ds->dpy_update = vnc_dpy_update; | |
1139 | + vs->ds->dpy_resize = vnc_dpy_resize; | |
1140 | + vs->ds->dpy_refresh = vnc_dpy_refresh; | |
1141 | + | |
1142 | + memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row)); | |
1134 | 1143 | |
1135 | - addr.sin_family = AF_INET; | |
1136 | - addr.sin_port = htons(5900 + display); | |
1137 | - memset(&addr.sin_addr, 0, sizeof(addr.sin_addr)); | |
1144 | + vnc_dpy_resize(vs->ds, 640, 400); | |
1138 | 1145 | |
1139 | - reuse_addr = 1; | |
1140 | - ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR, | |
1141 | - (const char *)&reuse_addr, sizeof(reuse_addr)); | |
1142 | - if (ret == -1) { | |
1143 | - fprintf(stderr, "setsockopt() failed\n"); | |
1144 | - exit(1); | |
1146 | +#ifndef _WIN32 | |
1147 | + if (strstart(arg, "unix:", &p)) { | |
1148 | + addr = (struct sockaddr *)&uaddr; | |
1149 | + addrlen = sizeof(uaddr); | |
1150 | + | |
1151 | + vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0); | |
1152 | + if (vs->lsock == -1) { | |
1153 | + fprintf(stderr, "Could not create socket\n"); | |
1154 | + exit(1); | |
1155 | + } | |
1156 | + | |
1157 | + uaddr.sun_family = AF_UNIX; | |
1158 | + memset(uaddr.sun_path, 0, 108); | |
1159 | + snprintf(uaddr.sun_path, 108, "%s", p); | |
1160 | + | |
1161 | + unlink(uaddr.sun_path); | |
1162 | + } else | |
1163 | +#endif | |
1164 | + { | |
1165 | + addr = (struct sockaddr *)&iaddr; | |
1166 | + addrlen = sizeof(iaddr); | |
1167 | + | |
1168 | + vs->lsock = socket(PF_INET, SOCK_STREAM, 0); | |
1169 | + if (vs->lsock == -1) { | |
1170 | + fprintf(stderr, "Could not create socket\n"); | |
1171 | + exit(1); | |
1172 | + } | |
1173 | + | |
1174 | + if (parse_host_port(&iaddr, arg) < 0) { | |
1175 | + fprintf(stderr, "Could not parse VNC address\n"); | |
1176 | + exit(1); | |
1177 | + } | |
1178 | + | |
1179 | + iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900); | |
1180 | + | |
1181 | + reuse_addr = 1; | |
1182 | + ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR, | |
1183 | + (const char *)&reuse_addr, sizeof(reuse_addr)); | |
1184 | + if (ret == -1) { | |
1185 | + fprintf(stderr, "setsockopt() failed\n"); | |
1186 | + exit(1); | |
1187 | + } | |
1145 | 1188 | } |
1146 | 1189 | |
1147 | - if (bind(vs->lsock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { | |
1190 | + if (bind(vs->lsock, addr, addrlen) == -1) { | |
1148 | 1191 | fprintf(stderr, "bind() failed\n"); |
1149 | 1192 | exit(1); |
1150 | 1193 | } |
... | ... | @@ -1158,13 +1201,4 @@ void vnc_display_init(DisplayState *ds, int display) |
1158 | 1201 | if (ret == -1) { |
1159 | 1202 | exit(1); |
1160 | 1203 | } |
1161 | - | |
1162 | - vs->ds->data = NULL; | |
1163 | - vs->ds->dpy_update = vnc_dpy_update; | |
1164 | - vs->ds->dpy_resize = vnc_dpy_resize; | |
1165 | - vs->ds->dpy_refresh = vnc_dpy_refresh; | |
1166 | - | |
1167 | - memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row)); | |
1168 | - | |
1169 | - vnc_dpy_resize(vs->ds, 640, 400); | |
1170 | 1204 | } | ... | ... |