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,14 +247,21 @@ command line application. The emulated serial port is redirected on | ||
247 | the console. Therefore, you can still use QEMU to debug a Linux kernel | 247 | the console. Therefore, you can still use QEMU to debug a Linux kernel |
248 | with a serial console. | 248 | with a serial console. |
249 | 249 | ||
250 | -@item -vnc d | 250 | +@item -vnc display |
251 | 251 | ||
252 | Normally, QEMU uses SDL to display the VGA output. With this option, | 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 | display over the VNC session. It is very useful to enable the usb | 254 | display over the VNC session. It is very useful to enable the usb |
255 | tablet device when using this option (option @option{-usbdevice | 255 | tablet device when using this option (option @option{-usbdevice |
256 | tablet}). When using the VNC display, you must use the @option{-k} | 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 | @item -k language | 266 | @item -k language |
260 | 267 |
vl.c
@@ -152,7 +152,7 @@ int win2k_install_hack = 0; | @@ -152,7 +152,7 @@ int win2k_install_hack = 0; | ||
152 | int usb_enabled = 0; | 152 | int usb_enabled = 0; |
153 | static VLANState *first_vlan; | 153 | static VLANState *first_vlan; |
154 | int smp_cpus = 1; | 154 | int smp_cpus = 1; |
155 | -int vnc_display = -1; | 155 | +const char *vnc_display; |
156 | #if defined(TARGET_SPARC) | 156 | #if defined(TARGET_SPARC) |
157 | #define MAX_CPUS 16 | 157 | #define MAX_CPUS 16 |
158 | #elif defined(TARGET_I386) | 158 | #elif defined(TARGET_I386) |
@@ -6818,11 +6818,7 @@ int main(int argc, char **argv) | @@ -6818,11 +6818,7 @@ int main(int argc, char **argv) | ||
6818 | } | 6818 | } |
6819 | break; | 6819 | break; |
6820 | case QEMU_OPTION_vnc: | 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 | break; | 6822 | break; |
6827 | case QEMU_OPTION_no_acpi: | 6823 | case QEMU_OPTION_no_acpi: |
6828 | acpi_enabled = 0; | 6824 | acpi_enabled = 0; |
@@ -6946,7 +6942,7 @@ int main(int argc, char **argv) | @@ -6946,7 +6942,7 @@ int main(int argc, char **argv) | ||
6946 | /* terminal init */ | 6942 | /* terminal init */ |
6947 | if (nographic) { | 6943 | if (nographic) { |
6948 | dumb_display_init(ds); | 6944 | dumb_display_init(ds); |
6949 | - } else if (vnc_display != -1) { | 6945 | + } else if (vnc_display != NULL) { |
6950 | vnc_display_init(ds, vnc_display); | 6946 | vnc_display_init(ds, vnc_display); |
6951 | } else { | 6947 | } else { |
6952 | #if defined(CONFIG_SDL) | 6948 | #if defined(CONFIG_SDL) |
vl.h
@@ -867,7 +867,7 @@ void sdl_display_init(DisplayState *ds, int full_screen); | @@ -867,7 +867,7 @@ void sdl_display_init(DisplayState *ds, int full_screen); | ||
867 | void cocoa_display_init(DisplayState *ds, int full_screen); | 867 | void cocoa_display_init(DisplayState *ds, int full_screen); |
868 | 868 | ||
869 | /* vnc.c */ | 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 | /* ide.c */ | 872 | /* ide.c */ |
873 | #define MAX_DISKS 4 | 873 | #define MAX_DISKS 4 |
vnc.c
@@ -1101,10 +1101,18 @@ static void vnc_listen_read(void *opaque) | @@ -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 | int reuse_addr, ret; | 1113 | int reuse_addr, ret; |
1114 | + socklen_t addrlen; | ||
1115 | + const char *p; | ||
1108 | VncState *vs; | 1116 | VncState *vs; |
1109 | 1117 | ||
1110 | vs = qemu_mallocz(sizeof(VncState)); | 1118 | vs = qemu_mallocz(sizeof(VncState)); |
@@ -1126,25 +1134,60 @@ void vnc_display_init(DisplayState *ds, int display) | @@ -1126,25 +1134,60 @@ void vnc_display_init(DisplayState *ds, int display) | ||
1126 | if (!vs->kbd_layout) | 1134 | if (!vs->kbd_layout) |
1127 | exit(1); | 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 | fprintf(stderr, "bind() failed\n"); | 1191 | fprintf(stderr, "bind() failed\n"); |
1149 | exit(1); | 1192 | exit(1); |
1150 | } | 1193 | } |
@@ -1158,13 +1201,4 @@ void vnc_display_init(DisplayState *ds, int display) | @@ -1158,13 +1201,4 @@ void vnc_display_init(DisplayState *ds, int display) | ||
1158 | if (ret == -1) { | 1201 | if (ret == -1) { |
1159 | exit(1); | 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 | } |