2 * QEMU VNC display driver
4 * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
5 * Copyright (C) 2006 Fabrice Bellard
6 * Copyright (C) 2009 Red Hat, Inc
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 #include "qemu/osdep.h"
32 #include "sysemu/sysemu.h"
33 #include "qemu/error-report.h"
34 #include "qemu/sockets.h"
35 #include "qemu/timer.h"
37 #include "qemu/config-file.h"
38 #include "qapi/qmp/qerror.h"
39 #include "qapi/qmp/types.h"
40 #include "qmp-commands.h"
42 #include "qapi-event.h"
43 #include "crypto/hash.h"
44 #include "crypto/tlscredsanon.h"
45 #include "crypto/tlscredsx509.h"
46 #include "qom/object_interfaces.h"
47 #include "qemu/cutils.h"
49 #define VNC_REFRESH_INTERVAL_BASE GUI_REFRESH_INTERVAL_DEFAULT
50 #define VNC_REFRESH_INTERVAL_INC 50
51 #define VNC_REFRESH_INTERVAL_MAX GUI_REFRESH_INTERVAL_IDLE
52 static const struct timeval VNC_REFRESH_STATS
= { 0, 500000 };
53 static const struct timeval VNC_REFRESH_LOSSY
= { 2, 0 };
55 #include "vnc_keysym.h"
56 #include "crypto/cipher.h"
58 static QTAILQ_HEAD(, VncDisplay
) vnc_displays
=
59 QTAILQ_HEAD_INITIALIZER(vnc_displays
);
61 static int vnc_cursor_define(VncState
*vs
);
62 static void vnc_release_modifiers(VncState
*vs
);
64 static void vnc_set_share_mode(VncState
*vs
, VncShareMode mode
)
67 static const char *mn
[] = {
69 [VNC_SHARE_MODE_CONNECTING
] = "connecting",
70 [VNC_SHARE_MODE_SHARED
] = "shared",
71 [VNC_SHARE_MODE_EXCLUSIVE
] = "exclusive",
72 [VNC_SHARE_MODE_DISCONNECTED
] = "disconnected",
74 fprintf(stderr
, "%s/%p: %s -> %s\n", __func__
,
75 vs
->ioc
, mn
[vs
->share_mode
], mn
[mode
]);
78 switch (vs
->share_mode
) {
79 case VNC_SHARE_MODE_CONNECTING
:
80 vs
->vd
->num_connecting
--;
82 case VNC_SHARE_MODE_SHARED
:
85 case VNC_SHARE_MODE_EXCLUSIVE
:
86 vs
->vd
->num_exclusive
--;
92 vs
->share_mode
= mode
;
94 switch (vs
->share_mode
) {
95 case VNC_SHARE_MODE_CONNECTING
:
96 vs
->vd
->num_connecting
++;
98 case VNC_SHARE_MODE_SHARED
:
101 case VNC_SHARE_MODE_EXCLUSIVE
:
102 vs
->vd
->num_exclusive
++;
110 static void vnc_init_basic_info(SocketAddress
*addr
,
114 switch (addr
->type
) {
115 case SOCKET_ADDRESS_KIND_INET
:
116 info
->host
= g_strdup(addr
->u
.inet
.data
->host
);
117 info
->service
= g_strdup(addr
->u
.inet
.data
->port
);
118 if (addr
->u
.inet
.data
->ipv6
) {
119 info
->family
= NETWORK_ADDRESS_FAMILY_IPV6
;
121 info
->family
= NETWORK_ADDRESS_FAMILY_IPV4
;
125 case SOCKET_ADDRESS_KIND_UNIX
:
126 info
->host
= g_strdup("");
127 info
->service
= g_strdup(addr
->u
.q_unix
.data
->path
);
128 info
->family
= NETWORK_ADDRESS_FAMILY_UNIX
;
132 error_setg(errp
, "Unsupported socket kind %d",
140 static void vnc_init_basic_info_from_server_addr(QIOChannelSocket
*ioc
,
144 SocketAddress
*addr
= NULL
;
147 error_setg(errp
, "No listener socket available");
151 addr
= qio_channel_socket_get_local_address(ioc
, errp
);
156 vnc_init_basic_info(addr
, info
, errp
);
157 qapi_free_SocketAddress(addr
);
160 static void vnc_init_basic_info_from_remote_addr(QIOChannelSocket
*ioc
,
164 SocketAddress
*addr
= NULL
;
166 addr
= qio_channel_socket_get_remote_address(ioc
, errp
);
171 vnc_init_basic_info(addr
, info
, errp
);
172 qapi_free_SocketAddress(addr
);
175 static const char *vnc_auth_name(VncDisplay
*vd
) {
177 case VNC_AUTH_INVALID
:
193 case VNC_AUTH_VENCRYPT
:
194 switch (vd
->subauth
) {
195 case VNC_AUTH_VENCRYPT_PLAIN
:
196 return "vencrypt+plain";
197 case VNC_AUTH_VENCRYPT_TLSNONE
:
198 return "vencrypt+tls+none";
199 case VNC_AUTH_VENCRYPT_TLSVNC
:
200 return "vencrypt+tls+vnc";
201 case VNC_AUTH_VENCRYPT_TLSPLAIN
:
202 return "vencrypt+tls+plain";
203 case VNC_AUTH_VENCRYPT_X509NONE
:
204 return "vencrypt+x509+none";
205 case VNC_AUTH_VENCRYPT_X509VNC
:
206 return "vencrypt+x509+vnc";
207 case VNC_AUTH_VENCRYPT_X509PLAIN
:
208 return "vencrypt+x509+plain";
209 case VNC_AUTH_VENCRYPT_TLSSASL
:
210 return "vencrypt+tls+sasl";
211 case VNC_AUTH_VENCRYPT_X509SASL
:
212 return "vencrypt+x509+sasl";
222 static VncServerInfo
*vnc_server_info_get(VncDisplay
*vd
)
227 info
= g_malloc0(sizeof(*info
));
228 vnc_init_basic_info_from_server_addr(vd
->lsock
,
229 qapi_VncServerInfo_base(info
), &err
);
230 info
->has_auth
= true;
231 info
->auth
= g_strdup(vnc_auth_name(vd
));
233 qapi_free_VncServerInfo(info
);
240 static void vnc_client_cache_auth(VncState
*client
)
247 client
->info
->x509_dname
=
248 qcrypto_tls_session_get_peer_name(client
->tls
);
249 client
->info
->has_x509_dname
=
250 client
->info
->x509_dname
!= NULL
;
252 #ifdef CONFIG_VNC_SASL
253 if (client
->sasl
.conn
&&
254 client
->sasl
.username
) {
255 client
->info
->has_sasl_username
= true;
256 client
->info
->sasl_username
= g_strdup(client
->sasl
.username
);
261 static void vnc_client_cache_addr(VncState
*client
)
265 client
->info
= g_malloc0(sizeof(*client
->info
));
266 vnc_init_basic_info_from_remote_addr(client
->sioc
,
267 qapi_VncClientInfo_base(client
->info
),
270 qapi_free_VncClientInfo(client
->info
);
276 static void vnc_qmp_event(VncState
*vs
, QAPIEvent event
)
284 si
= vnc_server_info_get(vs
->vd
);
290 case QAPI_EVENT_VNC_CONNECTED
:
291 qapi_event_send_vnc_connected(si
, qapi_VncClientInfo_base(vs
->info
),
294 case QAPI_EVENT_VNC_INITIALIZED
:
295 qapi_event_send_vnc_initialized(si
, vs
->info
, &error_abort
);
297 case QAPI_EVENT_VNC_DISCONNECTED
:
298 qapi_event_send_vnc_disconnected(si
, vs
->info
, &error_abort
);
304 qapi_free_VncServerInfo(si
);
307 static VncClientInfo
*qmp_query_vnc_client(const VncState
*client
)
312 info
= g_malloc0(sizeof(*info
));
314 vnc_init_basic_info_from_remote_addr(client
->sioc
,
315 qapi_VncClientInfo_base(info
),
319 qapi_free_VncClientInfo(info
);
323 info
->websocket
= client
->websocket
;
326 info
->x509_dname
= qcrypto_tls_session_get_peer_name(client
->tls
);
327 info
->has_x509_dname
= info
->x509_dname
!= NULL
;
329 #ifdef CONFIG_VNC_SASL
330 if (client
->sasl
.conn
&& client
->sasl
.username
) {
331 info
->has_sasl_username
= true;
332 info
->sasl_username
= g_strdup(client
->sasl
.username
);
339 static VncDisplay
*vnc_display_find(const char *id
)
344 return QTAILQ_FIRST(&vnc_displays
);
346 QTAILQ_FOREACH(vd
, &vnc_displays
, next
) {
347 if (strcmp(id
, vd
->id
) == 0) {
354 static VncClientInfoList
*qmp_query_client_list(VncDisplay
*vd
)
356 VncClientInfoList
*cinfo
, *prev
= NULL
;
359 QTAILQ_FOREACH(client
, &vd
->clients
, next
) {
360 cinfo
= g_new0(VncClientInfoList
, 1);
361 cinfo
->value
= qmp_query_vnc_client(client
);
368 VncInfo
*qmp_query_vnc(Error
**errp
)
370 VncInfo
*info
= g_malloc0(sizeof(*info
));
371 VncDisplay
*vd
= vnc_display_find(NULL
);
372 SocketAddress
*addr
= NULL
;
374 if (vd
== NULL
|| !vd
->lsock
) {
375 info
->enabled
= false;
377 info
->enabled
= true;
379 /* for compatibility with the original command */
380 info
->has_clients
= true;
381 info
->clients
= qmp_query_client_list(vd
);
383 if (vd
->lsock
== NULL
) {
387 addr
= qio_channel_socket_get_local_address(vd
->lsock
, errp
);
392 switch (addr
->type
) {
393 case SOCKET_ADDRESS_KIND_INET
:
394 info
->host
= g_strdup(addr
->u
.inet
.data
->host
);
395 info
->service
= g_strdup(addr
->u
.inet
.data
->port
);
396 if (addr
->u
.inet
.data
->ipv6
) {
397 info
->family
= NETWORK_ADDRESS_FAMILY_IPV6
;
399 info
->family
= NETWORK_ADDRESS_FAMILY_IPV4
;
403 case SOCKET_ADDRESS_KIND_UNIX
:
404 info
->host
= g_strdup("");
405 info
->service
= g_strdup(addr
->u
.q_unix
.data
->path
);
406 info
->family
= NETWORK_ADDRESS_FAMILY_UNIX
;
410 error_setg(errp
, "Unsupported socket kind %d",
415 info
->has_host
= true;
416 info
->has_service
= true;
417 info
->has_family
= true;
419 info
->has_auth
= true;
420 info
->auth
= g_strdup(vnc_auth_name(vd
));
423 qapi_free_SocketAddress(addr
);
427 qapi_free_SocketAddress(addr
);
428 qapi_free_VncInfo(info
);
432 static VncBasicInfoList
*qmp_query_server_entry(QIOChannelSocket
*ioc
,
434 VncBasicInfoList
*prev
)
436 VncBasicInfoList
*list
;
441 addr
= qio_channel_socket_get_local_address(ioc
, &err
);
447 info
= g_new0(VncBasicInfo
, 1);
448 vnc_init_basic_info(addr
, info
, &err
);
449 qapi_free_SocketAddress(addr
);
451 qapi_free_VncBasicInfo(info
);
455 info
->websocket
= websocket
;
457 list
= g_new0(VncBasicInfoList
, 1);
463 static void qmp_query_auth(VncDisplay
*vd
, VncInfo2
*info
)
467 info
->auth
= VNC_PRIMARY_AUTH_VNC
;
470 info
->auth
= VNC_PRIMARY_AUTH_RA2
;
473 info
->auth
= VNC_PRIMARY_AUTH_RA2NE
;
476 info
->auth
= VNC_PRIMARY_AUTH_TIGHT
;
479 info
->auth
= VNC_PRIMARY_AUTH_ULTRA
;
482 info
->auth
= VNC_PRIMARY_AUTH_TLS
;
484 case VNC_AUTH_VENCRYPT
:
485 info
->auth
= VNC_PRIMARY_AUTH_VENCRYPT
;
486 info
->has_vencrypt
= true;
487 switch (vd
->subauth
) {
488 case VNC_AUTH_VENCRYPT_PLAIN
:
489 info
->vencrypt
= VNC_VENCRYPT_SUB_AUTH_PLAIN
;
491 case VNC_AUTH_VENCRYPT_TLSNONE
:
492 info
->vencrypt
= VNC_VENCRYPT_SUB_AUTH_TLS_NONE
;
494 case VNC_AUTH_VENCRYPT_TLSVNC
:
495 info
->vencrypt
= VNC_VENCRYPT_SUB_AUTH_TLS_VNC
;
497 case VNC_AUTH_VENCRYPT_TLSPLAIN
:
498 info
->vencrypt
= VNC_VENCRYPT_SUB_AUTH_TLS_PLAIN
;
500 case VNC_AUTH_VENCRYPT_X509NONE
:
501 info
->vencrypt
= VNC_VENCRYPT_SUB_AUTH_X509_NONE
;
503 case VNC_AUTH_VENCRYPT_X509VNC
:
504 info
->vencrypt
= VNC_VENCRYPT_SUB_AUTH_X509_VNC
;
506 case VNC_AUTH_VENCRYPT_X509PLAIN
:
507 info
->vencrypt
= VNC_VENCRYPT_SUB_AUTH_X509_PLAIN
;
509 case VNC_AUTH_VENCRYPT_TLSSASL
:
510 info
->vencrypt
= VNC_VENCRYPT_SUB_AUTH_TLS_SASL
;
512 case VNC_AUTH_VENCRYPT_X509SASL
:
513 info
->vencrypt
= VNC_VENCRYPT_SUB_AUTH_X509_SASL
;
516 info
->has_vencrypt
= false;
521 info
->auth
= VNC_PRIMARY_AUTH_SASL
;
525 info
->auth
= VNC_PRIMARY_AUTH_NONE
;
530 VncInfo2List
*qmp_query_vnc_servers(Error
**errp
)
532 VncInfo2List
*item
, *prev
= NULL
;
537 QTAILQ_FOREACH(vd
, &vnc_displays
, next
) {
538 info
= g_new0(VncInfo2
, 1);
539 info
->id
= g_strdup(vd
->id
);
540 info
->clients
= qmp_query_client_list(vd
);
541 qmp_query_auth(vd
, info
);
543 dev
= DEVICE(object_property_get_link(OBJECT(vd
->dcl
.con
),
545 info
->has_display
= true;
546 info
->display
= g_strdup(dev
->id
);
548 if (vd
->lsock
!= NULL
) {
549 info
->server
= qmp_query_server_entry(
550 vd
->lsock
, false, info
->server
);
552 if (vd
->lwebsock
!= NULL
) {
553 info
->server
= qmp_query_server_entry(
554 vd
->lwebsock
, true, info
->server
);
557 item
= g_new0(VncInfo2List
, 1);
566 1) Get the queue working for IO.
567 2) there is some weirdness when using the -S option (the screen is grey
568 and not totally invalidated
569 3) resolutions > 1024
572 static int vnc_update_client(VncState
*vs
, int has_dirty
, bool sync
);
573 static void vnc_disconnect_start(VncState
*vs
);
575 static void vnc_colordepth(VncState
*vs
);
576 static void framebuffer_update_request(VncState
*vs
, int incremental
,
577 int x_position
, int y_position
,
579 static void vnc_refresh(DisplayChangeListener
*dcl
);
580 static int vnc_refresh_server_surface(VncDisplay
*vd
);
582 static int vnc_width(VncDisplay
*vd
)
584 return MIN(VNC_MAX_WIDTH
, ROUND_UP(surface_width(vd
->ds
),
585 VNC_DIRTY_PIXELS_PER_BIT
));
588 static int vnc_height(VncDisplay
*vd
)
590 return MIN(VNC_MAX_HEIGHT
, surface_height(vd
->ds
));
593 static void vnc_set_area_dirty(DECLARE_BITMAP(dirty
[VNC_MAX_HEIGHT
],
594 VNC_MAX_WIDTH
/ VNC_DIRTY_PIXELS_PER_BIT
),
596 int x
, int y
, int w
, int h
)
598 int width
= vnc_width(vd
);
599 int height
= vnc_height(vd
);
601 /* this is needed this to ensure we updated all affected
602 * blocks if x % VNC_DIRTY_PIXELS_PER_BIT != 0 */
603 w
+= (x
% VNC_DIRTY_PIXELS_PER_BIT
);
604 x
-= (x
% VNC_DIRTY_PIXELS_PER_BIT
);
608 w
= MIN(x
+ w
, width
) - x
;
609 h
= MIN(y
+ h
, height
);
612 bitmap_set(dirty
[y
], x
/ VNC_DIRTY_PIXELS_PER_BIT
,
613 DIV_ROUND_UP(w
, VNC_DIRTY_PIXELS_PER_BIT
));
617 static void vnc_dpy_update(DisplayChangeListener
*dcl
,
618 int x
, int y
, int w
, int h
)
620 VncDisplay
*vd
= container_of(dcl
, VncDisplay
, dcl
);
621 struct VncSurface
*s
= &vd
->guest
;
623 vnc_set_area_dirty(s
->dirty
, vd
, x
, y
, w
, h
);
626 void vnc_framebuffer_update(VncState
*vs
, int x
, int y
, int w
, int h
,
629 vnc_write_u16(vs
, x
);
630 vnc_write_u16(vs
, y
);
631 vnc_write_u16(vs
, w
);
632 vnc_write_u16(vs
, h
);
634 vnc_write_s32(vs
, encoding
);
638 static void vnc_desktop_resize(VncState
*vs
)
640 if (vs
->ioc
== NULL
|| !vnc_has_feature(vs
, VNC_FEATURE_RESIZE
)) {
643 if (vs
->client_width
== pixman_image_get_width(vs
->vd
->server
) &&
644 vs
->client_height
== pixman_image_get_height(vs
->vd
->server
)) {
647 vs
->client_width
= pixman_image_get_width(vs
->vd
->server
);
648 vs
->client_height
= pixman_image_get_height(vs
->vd
->server
);
650 vnc_write_u8(vs
, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE
);
652 vnc_write_u16(vs
, 1); /* number of rects */
653 vnc_framebuffer_update(vs
, 0, 0, vs
->client_width
, vs
->client_height
,
654 VNC_ENCODING_DESKTOPRESIZE
);
655 vnc_unlock_output(vs
);
659 static void vnc_abort_display_jobs(VncDisplay
*vd
)
663 QTAILQ_FOREACH(vs
, &vd
->clients
, next
) {
666 vnc_unlock_output(vs
);
668 QTAILQ_FOREACH(vs
, &vd
->clients
, next
) {
671 QTAILQ_FOREACH(vs
, &vd
->clients
, next
) {
674 vnc_unlock_output(vs
);
678 int vnc_server_fb_stride(VncDisplay
*vd
)
680 return pixman_image_get_stride(vd
->server
);
683 void *vnc_server_fb_ptr(VncDisplay
*vd
, int x
, int y
)
687 ptr
= (uint8_t *)pixman_image_get_data(vd
->server
);
688 ptr
+= y
* vnc_server_fb_stride(vd
);
689 ptr
+= x
* VNC_SERVER_FB_BYTES
;
693 static void vnc_update_server_surface(VncDisplay
*vd
)
697 qemu_pixman_image_unref(vd
->server
);
700 if (QTAILQ_EMPTY(&vd
->clients
)) {
704 width
= vnc_width(vd
);
705 height
= vnc_height(vd
);
706 vd
->server
= pixman_image_create_bits(VNC_SERVER_FB_FORMAT
,
710 memset(vd
->guest
.dirty
, 0x00, sizeof(vd
->guest
.dirty
));
711 vnc_set_area_dirty(vd
->guest
.dirty
, vd
, 0, 0,
715 static void vnc_dpy_switch(DisplayChangeListener
*dcl
,
716 DisplaySurface
*surface
)
718 VncDisplay
*vd
= container_of(dcl
, VncDisplay
, dcl
);
721 vnc_abort_display_jobs(vd
);
725 vnc_update_server_surface(vd
);
728 qemu_pixman_image_unref(vd
->guest
.fb
);
729 vd
->guest
.fb
= pixman_image_ref(surface
->image
);
730 vd
->guest
.format
= surface
->format
;
732 QTAILQ_FOREACH(vs
, &vd
->clients
, next
) {
734 vnc_desktop_resize(vs
);
735 if (vs
->vd
->cursor
) {
736 vnc_cursor_define(vs
);
738 memset(vs
->dirty
, 0x00, sizeof(vs
->dirty
));
739 vnc_set_area_dirty(vs
->dirty
, vd
, 0, 0,
746 static void vnc_write_pixels_copy(VncState
*vs
,
747 void *pixels
, int size
)
749 vnc_write(vs
, pixels
, size
);
752 /* slowest but generic code. */
753 void vnc_convert_pixel(VncState
*vs
, uint8_t *buf
, uint32_t v
)
757 #if VNC_SERVER_FB_FORMAT == PIXMAN_FORMAT(32, PIXMAN_TYPE_ARGB, 0, 8, 8, 8)
758 r
= (((v
& 0x00ff0000) >> 16) << vs
->client_pf
.rbits
) >> 8;
759 g
= (((v
& 0x0000ff00) >> 8) << vs
->client_pf
.gbits
) >> 8;
760 b
= (((v
& 0x000000ff) >> 0) << vs
->client_pf
.bbits
) >> 8;
762 # error need some bits here if you change VNC_SERVER_FB_FORMAT
764 v
= (r
<< vs
->client_pf
.rshift
) |
765 (g
<< vs
->client_pf
.gshift
) |
766 (b
<< vs
->client_pf
.bshift
);
767 switch (vs
->client_pf
.bytes_per_pixel
) {
797 static void vnc_write_pixels_generic(VncState
*vs
,
798 void *pixels1
, int size
)
802 if (VNC_SERVER_FB_BYTES
== 4) {
803 uint32_t *pixels
= pixels1
;
806 for (i
= 0; i
< n
; i
++) {
807 vnc_convert_pixel(vs
, buf
, pixels
[i
]);
808 vnc_write(vs
, buf
, vs
->client_pf
.bytes_per_pixel
);
813 int vnc_raw_send_framebuffer_update(VncState
*vs
, int x
, int y
, int w
, int h
)
817 VncDisplay
*vd
= vs
->vd
;
819 row
= vnc_server_fb_ptr(vd
, x
, y
);
820 for (i
= 0; i
< h
; i
++) {
821 vs
->write_pixels(vs
, row
, w
* VNC_SERVER_FB_BYTES
);
822 row
+= vnc_server_fb_stride(vd
);
827 int vnc_send_framebuffer_update(VncState
*vs
, int x
, int y
, int w
, int h
)
830 bool encode_raw
= false;
831 size_t saved_offs
= vs
->output
.offset
;
833 switch(vs
->vnc_encoding
) {
834 case VNC_ENCODING_ZLIB
:
835 n
= vnc_zlib_send_framebuffer_update(vs
, x
, y
, w
, h
);
837 case VNC_ENCODING_HEXTILE
:
838 vnc_framebuffer_update(vs
, x
, y
, w
, h
, VNC_ENCODING_HEXTILE
);
839 n
= vnc_hextile_send_framebuffer_update(vs
, x
, y
, w
, h
);
841 case VNC_ENCODING_TIGHT
:
842 n
= vnc_tight_send_framebuffer_update(vs
, x
, y
, w
, h
);
844 case VNC_ENCODING_TIGHT_PNG
:
845 n
= vnc_tight_png_send_framebuffer_update(vs
, x
, y
, w
, h
);
847 case VNC_ENCODING_ZRLE
:
848 n
= vnc_zrle_send_framebuffer_update(vs
, x
, y
, w
, h
);
850 case VNC_ENCODING_ZYWRLE
:
851 n
= vnc_zywrle_send_framebuffer_update(vs
, x
, y
, w
, h
);
858 /* If the client has the same pixel format as our internal buffer and
859 * a RAW encoding would need less space fall back to RAW encoding to
860 * save bandwidth and processing power in the client. */
861 if (!encode_raw
&& vs
->write_pixels
== vnc_write_pixels_copy
&&
862 12 + h
* w
* VNC_SERVER_FB_BYTES
<= (vs
->output
.offset
- saved_offs
)) {
863 vs
->output
.offset
= saved_offs
;
868 vnc_framebuffer_update(vs
, x
, y
, w
, h
, VNC_ENCODING_RAW
);
869 n
= vnc_raw_send_framebuffer_update(vs
, x
, y
, w
, h
);
875 static void vnc_copy(VncState
*vs
, int src_x
, int src_y
, int dst_x
, int dst_y
, int w
, int h
)
877 /* send bitblit op to the vnc client */
879 vnc_write_u8(vs
, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE
);
881 vnc_write_u16(vs
, 1); /* number of rects */
882 vnc_framebuffer_update(vs
, dst_x
, dst_y
, w
, h
, VNC_ENCODING_COPYRECT
);
883 vnc_write_u16(vs
, src_x
);
884 vnc_write_u16(vs
, src_y
);
885 vnc_unlock_output(vs
);
889 static void vnc_dpy_copy(DisplayChangeListener
*dcl
,
890 int src_x
, int src_y
,
891 int dst_x
, int dst_y
, int w
, int h
)
893 VncDisplay
*vd
= container_of(dcl
, VncDisplay
, dcl
);
897 int i
, x
, y
, pitch
, inc
, w_lim
, s
;
901 /* no client connected */
905 vnc_refresh_server_surface(vd
);
906 QTAILQ_FOREACH_SAFE(vs
, &vd
->clients
, next
, vn
) {
907 if (vnc_has_feature(vs
, VNC_FEATURE_COPYRECT
)) {
908 vs
->force_update
= 1;
909 vnc_update_client(vs
, 1, true);
910 /* vs might be free()ed here */
915 /* no client connected */
918 /* do bitblit op on the local surface too */
919 pitch
= vnc_server_fb_stride(vd
);
920 src_row
= vnc_server_fb_ptr(vd
, src_x
, src_y
);
921 dst_row
= vnc_server_fb_ptr(vd
, dst_x
, dst_y
);
926 src_row
+= pitch
* (h
-1);
927 dst_row
+= pitch
* (h
-1);
932 w_lim
= w
- (VNC_DIRTY_PIXELS_PER_BIT
- (dst_x
% VNC_DIRTY_PIXELS_PER_BIT
));
936 w_lim
= w
- (w_lim
% VNC_DIRTY_PIXELS_PER_BIT
);
938 for (i
= 0; i
< h
; i
++) {
939 for (x
= 0; x
<= w_lim
;
940 x
+= s
, src_row
+= cmp_bytes
, dst_row
+= cmp_bytes
) {
942 if ((s
= w
- w_lim
) == 0)
945 s
= (VNC_DIRTY_PIXELS_PER_BIT
-
946 (dst_x
% VNC_DIRTY_PIXELS_PER_BIT
));
949 s
= VNC_DIRTY_PIXELS_PER_BIT
;
951 cmp_bytes
= s
* VNC_SERVER_FB_BYTES
;
952 if (memcmp(src_row
, dst_row
, cmp_bytes
) == 0)
954 memmove(dst_row
, src_row
, cmp_bytes
);
955 QTAILQ_FOREACH(vs
, &vd
->clients
, next
) {
956 if (!vnc_has_feature(vs
, VNC_FEATURE_COPYRECT
)) {
957 set_bit(((x
+ dst_x
) / VNC_DIRTY_PIXELS_PER_BIT
),
962 src_row
+= pitch
- w
* VNC_SERVER_FB_BYTES
;
963 dst_row
+= pitch
- w
* VNC_SERVER_FB_BYTES
;
967 QTAILQ_FOREACH(vs
, &vd
->clients
, next
) {
968 if (vnc_has_feature(vs
, VNC_FEATURE_COPYRECT
)) {
969 vnc_copy(vs
, src_x
, src_y
, dst_x
, dst_y
, w
, h
);
974 static void vnc_mouse_set(DisplayChangeListener
*dcl
,
975 int x
, int y
, int visible
)
977 /* can we ask the client(s) to move the pointer ??? */
980 static int vnc_cursor_define(VncState
*vs
)
982 QEMUCursor
*c
= vs
->vd
->cursor
;
985 if (vnc_has_feature(vs
, VNC_FEATURE_RICH_CURSOR
)) {
987 vnc_write_u8(vs
, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE
);
988 vnc_write_u8(vs
, 0); /* padding */
989 vnc_write_u16(vs
, 1); /* # of rects */
990 vnc_framebuffer_update(vs
, c
->hot_x
, c
->hot_y
, c
->width
, c
->height
,
991 VNC_ENCODING_RICH_CURSOR
);
992 isize
= c
->width
* c
->height
* vs
->client_pf
.bytes_per_pixel
;
993 vnc_write_pixels_generic(vs
, c
->data
, isize
);
994 vnc_write(vs
, vs
->vd
->cursor_mask
, vs
->vd
->cursor_msize
);
995 vnc_unlock_output(vs
);
1001 static void vnc_dpy_cursor_define(DisplayChangeListener
*dcl
,
1004 VncDisplay
*vd
= container_of(dcl
, VncDisplay
, dcl
);
1007 cursor_put(vd
->cursor
);
1008 g_free(vd
->cursor_mask
);
1011 cursor_get(vd
->cursor
);
1012 vd
->cursor_msize
= cursor_get_mono_bpl(c
) * c
->height
;
1013 vd
->cursor_mask
= g_malloc0(vd
->cursor_msize
);
1014 cursor_get_mono_mask(c
, 0, vd
->cursor_mask
);
1016 QTAILQ_FOREACH(vs
, &vd
->clients
, next
) {
1017 vnc_cursor_define(vs
);
1021 static int find_and_clear_dirty_height(VncState
*vs
,
1022 int y
, int last_x
, int x
, int height
)
1026 for (h
= 1; h
< (height
- y
); h
++) {
1027 if (!test_bit(last_x
, vs
->dirty
[y
+ h
])) {
1030 bitmap_clear(vs
->dirty
[y
+ h
], last_x
, x
- last_x
);
1036 static int vnc_update_client(VncState
*vs
, int has_dirty
, bool sync
)
1038 if (vs
->disconnecting
) {
1039 vnc_disconnect_finish(vs
);
1043 vs
->has_dirty
+= has_dirty
;
1044 if (vs
->need_update
&& !vs
->disconnecting
) {
1045 VncDisplay
*vd
= vs
->vd
;
1051 if (vs
->output
.offset
&& !vs
->audio_cap
&& !vs
->force_update
)
1052 /* kernel send buffers are full -> drop frames to throttle */
1055 if (!vs
->has_dirty
&& !vs
->audio_cap
&& !vs
->force_update
)
1059 * Send screen updates to the vnc client using the server
1060 * surface and server dirty map. guest surface updates
1061 * happening in parallel don't disturb us, the next pass will
1062 * send them to the client.
1064 job
= vnc_job_new(vs
);
1066 height
= pixman_image_get_height(vd
->server
);
1067 width
= pixman_image_get_width(vd
->server
);
1073 unsigned long offset
= find_next_bit((unsigned long *) &vs
->dirty
,
1074 height
* VNC_DIRTY_BPL(vs
),
1075 y
* VNC_DIRTY_BPL(vs
));
1076 if (offset
== height
* VNC_DIRTY_BPL(vs
)) {
1077 /* no more dirty bits */
1080 y
= offset
/ VNC_DIRTY_BPL(vs
);
1081 x
= offset
% VNC_DIRTY_BPL(vs
);
1082 x2
= find_next_zero_bit((unsigned long *) &vs
->dirty
[y
],
1083 VNC_DIRTY_BPL(vs
), x
);
1084 bitmap_clear(vs
->dirty
[y
], x
, x2
- x
);
1085 h
= find_and_clear_dirty_height(vs
, y
, x
, x2
, height
);
1086 x2
= MIN(x2
, width
/ VNC_DIRTY_PIXELS_PER_BIT
);
1088 n
+= vnc_job_add_rect(job
, x
* VNC_DIRTY_PIXELS_PER_BIT
, y
,
1089 (x2
- x
) * VNC_DIRTY_PIXELS_PER_BIT
, h
);
1091 if (!x
&& x2
== width
/ VNC_DIRTY_PIXELS_PER_BIT
) {
1103 vs
->force_update
= 0;
1108 if (vs
->disconnecting
) {
1109 vnc_disconnect_finish(vs
);
1118 static void audio_capture_notify(void *opaque
, audcnotification_e cmd
)
1120 VncState
*vs
= opaque
;
1123 case AUD_CNOTIFY_DISABLE
:
1124 vnc_lock_output(vs
);
1125 vnc_write_u8(vs
, VNC_MSG_SERVER_QEMU
);
1126 vnc_write_u8(vs
, VNC_MSG_SERVER_QEMU_AUDIO
);
1127 vnc_write_u16(vs
, VNC_MSG_SERVER_QEMU_AUDIO_END
);
1128 vnc_unlock_output(vs
);
1132 case AUD_CNOTIFY_ENABLE
:
1133 vnc_lock_output(vs
);
1134 vnc_write_u8(vs
, VNC_MSG_SERVER_QEMU
);
1135 vnc_write_u8(vs
, VNC_MSG_SERVER_QEMU_AUDIO
);
1136 vnc_write_u16(vs
, VNC_MSG_SERVER_QEMU_AUDIO_BEGIN
);
1137 vnc_unlock_output(vs
);
1143 static void audio_capture_destroy(void *opaque
)
1147 static void audio_capture(void *opaque
, void *buf
, int size
)
1149 VncState
*vs
= opaque
;
1151 vnc_lock_output(vs
);
1152 vnc_write_u8(vs
, VNC_MSG_SERVER_QEMU
);
1153 vnc_write_u8(vs
, VNC_MSG_SERVER_QEMU_AUDIO
);
1154 vnc_write_u16(vs
, VNC_MSG_SERVER_QEMU_AUDIO_DATA
);
1155 vnc_write_u32(vs
, size
);
1156 vnc_write(vs
, buf
, size
);
1157 vnc_unlock_output(vs
);
1161 static void audio_add(VncState
*vs
)
1163 struct audio_capture_ops ops
;
1165 if (vs
->audio_cap
) {
1166 error_report("audio already running");
1170 ops
.notify
= audio_capture_notify
;
1171 ops
.destroy
= audio_capture_destroy
;
1172 ops
.capture
= audio_capture
;
1174 vs
->audio_cap
= AUD_add_capture(&vs
->as
, &ops
, vs
);
1175 if (!vs
->audio_cap
) {
1176 error_report("Failed to add audio capture");
1180 static void audio_del(VncState
*vs
)
1182 if (vs
->audio_cap
) {
1183 AUD_del_capture(vs
->audio_cap
, vs
);
1184 vs
->audio_cap
= NULL
;
1188 static void vnc_disconnect_start(VncState
*vs
)
1190 if (vs
->disconnecting
) {
1193 vnc_set_share_mode(vs
, VNC_SHARE_MODE_DISCONNECTED
);
1195 g_source_remove(vs
->ioc_tag
);
1197 qio_channel_close(vs
->ioc
, NULL
);
1198 vs
->disconnecting
= TRUE
;
1201 void vnc_disconnect_finish(VncState
*vs
)
1205 vnc_jobs_join(vs
); /* Wait encoding jobs */
1207 vnc_lock_output(vs
);
1208 vnc_qmp_event(vs
, QAPI_EVENT_VNC_DISCONNECTED
);
1210 buffer_free(&vs
->input
);
1211 buffer_free(&vs
->output
);
1213 qapi_free_VncClientInfo(vs
->info
);
1216 vnc_tight_clear(vs
);
1219 #ifdef CONFIG_VNC_SASL
1220 vnc_sasl_client_cleanup(vs
);
1221 #endif /* CONFIG_VNC_SASL */
1223 vnc_release_modifiers(vs
);
1225 if (vs
->mouse_mode_notifier
.notify
!= NULL
) {
1226 qemu_remove_mouse_mode_change_notifier(&vs
->mouse_mode_notifier
);
1228 QTAILQ_REMOVE(&vs
->vd
->clients
, vs
, next
);
1229 if (QTAILQ_EMPTY(&vs
->vd
->clients
)) {
1230 /* last client gone */
1231 vnc_update_server_surface(vs
->vd
);
1234 if (vs
->vd
->lock_key_sync
)
1235 qemu_remove_led_event_handler(vs
->led
);
1236 vnc_unlock_output(vs
);
1238 qemu_mutex_destroy(&vs
->output_mutex
);
1239 if (vs
->bh
!= NULL
) {
1240 qemu_bh_delete(vs
->bh
);
1242 buffer_free(&vs
->jobs_buffer
);
1244 for (i
= 0; i
< VNC_STAT_ROWS
; ++i
) {
1245 g_free(vs
->lossy_rect
[i
]);
1247 g_free(vs
->lossy_rect
);
1249 object_unref(OBJECT(vs
->ioc
));
1251 object_unref(OBJECT(vs
->sioc
));
1256 ssize_t
vnc_client_io_error(VncState
*vs
, ssize_t ret
, Error
**errp
)
1260 VNC_DEBUG("Closing down client sock: EOF\n");
1261 } else if (ret
!= QIO_CHANNEL_ERR_BLOCK
) {
1262 VNC_DEBUG("Closing down client sock: ret %d (%s)\n",
1263 ret
, errp
? error_get_pretty(*errp
) : "Unknown");
1266 vnc_disconnect_start(vs
);
1277 void vnc_client_error(VncState
*vs
)
1279 VNC_DEBUG("Closing down client sock: protocol error\n");
1280 vnc_disconnect_start(vs
);
1285 * Called to write a chunk of data to the client socket. The data may
1286 * be the raw data, or may have already been encoded by SASL.
1287 * The data will be written either straight onto the socket, or
1288 * written via the GNUTLS wrappers, if TLS/SSL encryption is enabled
1290 * NB, it is theoretically possible to have 2 layers of encryption,
1291 * both SASL, and this TLS layer. It is highly unlikely in practice
1292 * though, since SASL encryption will typically be a no-op if TLS
1295 * Returns the number of bytes written, which may be less than
1296 * the requested 'datalen' if the socket would block. Returns
1297 * -1 on error, and disconnects the client socket.
1299 ssize_t
vnc_client_write_buf(VncState
*vs
, const void *data
, size_t datalen
)
1303 ret
= qio_channel_write(
1304 vs
->ioc
, (const char *)data
, datalen
, &err
);
1305 VNC_DEBUG("Wrote wire %p %zd -> %ld\n", data
, datalen
, ret
);
1306 return vnc_client_io_error(vs
, ret
, &err
);
1311 * Called to write buffered data to the client socket, when not
1312 * using any SASL SSF encryption layers. Will write as much data
1313 * as possible without blocking. If all buffered data is written,
1314 * will switch the FD poll() handler back to read monitoring.
1316 * Returns the number of bytes written, which may be less than
1317 * the buffered output data if the socket would block. Returns
1318 * -1 on error, and disconnects the client socket.
1320 static ssize_t
vnc_client_write_plain(VncState
*vs
)
1324 #ifdef CONFIG_VNC_SASL
1325 VNC_DEBUG("Write Plain: Pending output %p size %zd offset %zd. Wait SSF %d\n",
1326 vs
->output
.buffer
, vs
->output
.capacity
, vs
->output
.offset
,
1327 vs
->sasl
.waitWriteSSF
);
1329 if (vs
->sasl
.conn
&&
1331 vs
->sasl
.waitWriteSSF
) {
1332 ret
= vnc_client_write_buf(vs
, vs
->output
.buffer
, vs
->sasl
.waitWriteSSF
);
1334 vs
->sasl
.waitWriteSSF
-= ret
;
1336 #endif /* CONFIG_VNC_SASL */
1337 ret
= vnc_client_write_buf(vs
, vs
->output
.buffer
, vs
->output
.offset
);
1341 buffer_advance(&vs
->output
, ret
);
1343 if (vs
->output
.offset
== 0) {
1345 g_source_remove(vs
->ioc_tag
);
1347 vs
->ioc_tag
= qio_channel_add_watch(
1348 vs
->ioc
, G_IO_IN
, vnc_client_io
, vs
, NULL
);
1356 * First function called whenever there is data to be written to
1357 * the client socket. Will delegate actual work according to whether
1358 * SASL SSF layers are enabled (thus requiring encryption calls)
1360 static void vnc_client_write_locked(VncState
*vs
)
1362 #ifdef CONFIG_VNC_SASL
1363 if (vs
->sasl
.conn
&&
1365 !vs
->sasl
.waitWriteSSF
) {
1366 vnc_client_write_sasl(vs
);
1368 #endif /* CONFIG_VNC_SASL */
1370 vnc_client_write_plain(vs
);
1374 static void vnc_client_write(VncState
*vs
)
1377 vnc_lock_output(vs
);
1378 if (vs
->output
.offset
) {
1379 vnc_client_write_locked(vs
);
1380 } else if (vs
->ioc
!= NULL
) {
1382 g_source_remove(vs
->ioc_tag
);
1384 vs
->ioc_tag
= qio_channel_add_watch(
1385 vs
->ioc
, G_IO_IN
, vnc_client_io
, vs
, NULL
);
1387 vnc_unlock_output(vs
);
1390 void vnc_read_when(VncState
*vs
, VncReadEvent
*func
, size_t expecting
)
1392 vs
->read_handler
= func
;
1393 vs
->read_handler_expect
= expecting
;
1398 * Called to read a chunk of data from the client socket. The data may
1399 * be the raw data, or may need to be further decoded by SASL.
1400 * The data will be read either straight from to the socket, or
1401 * read via the GNUTLS wrappers, if TLS/SSL encryption is enabled
1403 * NB, it is theoretically possible to have 2 layers of encryption,
1404 * both SASL, and this TLS layer. It is highly unlikely in practice
1405 * though, since SASL encryption will typically be a no-op if TLS
1408 * Returns the number of bytes read, which may be less than
1409 * the requested 'datalen' if the socket would block. Returns
1410 * -1 on error, and disconnects the client socket.
1412 ssize_t
vnc_client_read_buf(VncState
*vs
, void *data
, size_t datalen
)
1416 ret
= qio_channel_read(
1417 vs
->ioc
, (char *)data
, datalen
, &err
);
1418 VNC_DEBUG("Read wire %p %zd -> %ld\n", data
, datalen
, ret
);
1419 return vnc_client_io_error(vs
, ret
, &err
);
1424 * Called to read data from the client socket to the input buffer,
1425 * when not using any SASL SSF encryption layers. Will read as much
1426 * data as possible without blocking.
1428 * Returns the number of bytes read. Returns -1 on error, and
1429 * disconnects the client socket.
1431 static ssize_t
vnc_client_read_plain(VncState
*vs
)
1434 VNC_DEBUG("Read plain %p size %zd offset %zd\n",
1435 vs
->input
.buffer
, vs
->input
.capacity
, vs
->input
.offset
);
1436 buffer_reserve(&vs
->input
, 4096);
1437 ret
= vnc_client_read_buf(vs
, buffer_end(&vs
->input
), 4096);
1440 vs
->input
.offset
+= ret
;
1444 static void vnc_jobs_bh(void *opaque
)
1446 VncState
*vs
= opaque
;
1448 vnc_jobs_consume_buffer(vs
);
1452 * First function called whenever there is more data to be read from
1453 * the client socket. Will delegate actual work according to whether
1454 * SASL SSF layers are enabled (thus requiring decryption calls)
1455 * Returns 0 on success, -1 if client disconnected
1457 static int vnc_client_read(VncState
*vs
)
1461 #ifdef CONFIG_VNC_SASL
1462 if (vs
->sasl
.conn
&& vs
->sasl
.runSSF
)
1463 ret
= vnc_client_read_sasl(vs
);
1465 #endif /* CONFIG_VNC_SASL */
1466 ret
= vnc_client_read_plain(vs
);
1468 if (vs
->disconnecting
) {
1469 vnc_disconnect_finish(vs
);
1475 while (vs
->read_handler
&& vs
->input
.offset
>= vs
->read_handler_expect
) {
1476 size_t len
= vs
->read_handler_expect
;
1479 ret
= vs
->read_handler(vs
, vs
->input
.buffer
, len
);
1480 if (vs
->disconnecting
) {
1481 vnc_disconnect_finish(vs
);
1486 buffer_advance(&vs
->input
, len
);
1488 vs
->read_handler_expect
= ret
;
1494 gboolean
vnc_client_io(QIOChannel
*ioc G_GNUC_UNUSED
,
1495 GIOCondition condition
, void *opaque
)
1497 VncState
*vs
= opaque
;
1498 if (condition
& G_IO_IN
) {
1499 if (vnc_client_read(vs
) < 0) {
1503 if (condition
& G_IO_OUT
) {
1504 vnc_client_write(vs
);
1510 void vnc_write(VncState
*vs
, const void *data
, size_t len
)
1512 buffer_reserve(&vs
->output
, len
);
1514 if (vs
->ioc
!= NULL
&& buffer_empty(&vs
->output
)) {
1516 g_source_remove(vs
->ioc_tag
);
1518 vs
->ioc_tag
= qio_channel_add_watch(
1519 vs
->ioc
, G_IO_IN
| G_IO_OUT
, vnc_client_io
, vs
, NULL
);
1522 buffer_append(&vs
->output
, data
, len
);
1525 void vnc_write_s32(VncState
*vs
, int32_t value
)
1527 vnc_write_u32(vs
, *(uint32_t *)&value
);
1530 void vnc_write_u32(VncState
*vs
, uint32_t value
)
1534 buf
[0] = (value
>> 24) & 0xFF;
1535 buf
[1] = (value
>> 16) & 0xFF;
1536 buf
[2] = (value
>> 8) & 0xFF;
1537 buf
[3] = value
& 0xFF;
1539 vnc_write(vs
, buf
, 4);
1542 void vnc_write_u16(VncState
*vs
, uint16_t value
)
1546 buf
[0] = (value
>> 8) & 0xFF;
1547 buf
[1] = value
& 0xFF;
1549 vnc_write(vs
, buf
, 2);
1552 void vnc_write_u8(VncState
*vs
, uint8_t value
)
1554 vnc_write(vs
, (char *)&value
, 1);
1557 void vnc_flush(VncState
*vs
)
1559 vnc_lock_output(vs
);
1560 if (vs
->ioc
!= NULL
&& vs
->output
.offset
) {
1561 vnc_client_write_locked(vs
);
1563 vnc_unlock_output(vs
);
1566 static uint8_t read_u8(uint8_t *data
, size_t offset
)
1568 return data
[offset
];
1571 static uint16_t read_u16(uint8_t *data
, size_t offset
)
1573 return ((data
[offset
] & 0xFF) << 8) | (data
[offset
+ 1] & 0xFF);
1576 static int32_t read_s32(uint8_t *data
, size_t offset
)
1578 return (int32_t)((data
[offset
] << 24) | (data
[offset
+ 1] << 16) |
1579 (data
[offset
+ 2] << 8) | data
[offset
+ 3]);
1582 uint32_t read_u32(uint8_t *data
, size_t offset
)
1584 return ((data
[offset
] << 24) | (data
[offset
+ 1] << 16) |
1585 (data
[offset
+ 2] << 8) | data
[offset
+ 3]);
1588 static void client_cut_text(VncState
*vs
, size_t len
, uint8_t *text
)
1592 static void check_pointer_type_change(Notifier
*notifier
, void *data
)
1594 VncState
*vs
= container_of(notifier
, VncState
, mouse_mode_notifier
);
1595 int absolute
= qemu_input_is_absolute();
1597 if (vnc_has_feature(vs
, VNC_FEATURE_POINTER_TYPE_CHANGE
) && vs
->absolute
!= absolute
) {
1598 vnc_lock_output(vs
);
1599 vnc_write_u8(vs
, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE
);
1600 vnc_write_u8(vs
, 0);
1601 vnc_write_u16(vs
, 1);
1602 vnc_framebuffer_update(vs
, absolute
, 0,
1603 pixman_image_get_width(vs
->vd
->server
),
1604 pixman_image_get_height(vs
->vd
->server
),
1605 VNC_ENCODING_POINTER_TYPE_CHANGE
);
1606 vnc_unlock_output(vs
);
1609 vs
->absolute
= absolute
;
1612 static void pointer_event(VncState
*vs
, int button_mask
, int x
, int y
)
1614 static uint32_t bmap
[INPUT_BUTTON__MAX
] = {
1615 [INPUT_BUTTON_LEFT
] = 0x01,
1616 [INPUT_BUTTON_MIDDLE
] = 0x02,
1617 [INPUT_BUTTON_RIGHT
] = 0x04,
1618 [INPUT_BUTTON_WHEEL_UP
] = 0x08,
1619 [INPUT_BUTTON_WHEEL_DOWN
] = 0x10,
1621 QemuConsole
*con
= vs
->vd
->dcl
.con
;
1622 int width
= pixman_image_get_width(vs
->vd
->server
);
1623 int height
= pixman_image_get_height(vs
->vd
->server
);
1625 if (vs
->last_bmask
!= button_mask
) {
1626 qemu_input_update_buttons(con
, bmap
, vs
->last_bmask
, button_mask
);
1627 vs
->last_bmask
= button_mask
;
1631 qemu_input_queue_abs(con
, INPUT_AXIS_X
, x
, width
);
1632 qemu_input_queue_abs(con
, INPUT_AXIS_Y
, y
, height
);
1633 } else if (vnc_has_feature(vs
, VNC_FEATURE_POINTER_TYPE_CHANGE
)) {
1634 qemu_input_queue_rel(con
, INPUT_AXIS_X
, x
- 0x7FFF);
1635 qemu_input_queue_rel(con
, INPUT_AXIS_Y
, y
- 0x7FFF);
1637 if (vs
->last_x
!= -1) {
1638 qemu_input_queue_rel(con
, INPUT_AXIS_X
, x
- vs
->last_x
);
1639 qemu_input_queue_rel(con
, INPUT_AXIS_Y
, y
- vs
->last_y
);
1644 qemu_input_event_sync();
1647 static void reset_keys(VncState
*vs
)
1650 for(i
= 0; i
< 256; i
++) {
1651 if (vs
->modifiers_state
[i
]) {
1652 qemu_input_event_send_key_number(vs
->vd
->dcl
.con
, i
, false);
1653 qemu_input_event_send_key_delay(vs
->vd
->key_delay_ms
);
1654 vs
->modifiers_state
[i
] = 0;
1659 static void press_key(VncState
*vs
, int keysym
)
1661 int keycode
= keysym2scancode(vs
->vd
->kbd_layout
, keysym
) & SCANCODE_KEYMASK
;
1662 qemu_input_event_send_key_number(vs
->vd
->dcl
.con
, keycode
, true);
1663 qemu_input_event_send_key_delay(vs
->vd
->key_delay_ms
);
1664 qemu_input_event_send_key_number(vs
->vd
->dcl
.con
, keycode
, false);
1665 qemu_input_event_send_key_delay(vs
->vd
->key_delay_ms
);
1668 static int current_led_state(VncState
*vs
)
1672 if (vs
->modifiers_state
[0x46]) {
1673 ledstate
|= QEMU_SCROLL_LOCK_LED
;
1675 if (vs
->modifiers_state
[0x45]) {
1676 ledstate
|= QEMU_NUM_LOCK_LED
;
1678 if (vs
->modifiers_state
[0x3a]) {
1679 ledstate
|= QEMU_CAPS_LOCK_LED
;
1685 static void vnc_led_state_change(VncState
*vs
)
1689 if (!vnc_has_feature(vs
, VNC_FEATURE_LED_STATE
)) {
1693 ledstate
= current_led_state(vs
);
1694 vnc_lock_output(vs
);
1695 vnc_write_u8(vs
, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE
);
1696 vnc_write_u8(vs
, 0);
1697 vnc_write_u16(vs
, 1);
1698 vnc_framebuffer_update(vs
, 0, 0, 1, 1, VNC_ENCODING_LED_STATE
);
1699 vnc_write_u8(vs
, ledstate
);
1700 vnc_unlock_output(vs
);
1704 static void kbd_leds(void *opaque
, int ledstate
)
1706 VncState
*vs
= opaque
;
1708 bool has_changed
= (ledstate
!= current_led_state(vs
));
1710 trace_vnc_key_guest_leds((ledstate
& QEMU_CAPS_LOCK_LED
),
1711 (ledstate
& QEMU_NUM_LOCK_LED
),
1712 (ledstate
& QEMU_SCROLL_LOCK_LED
));
1714 caps
= ledstate
& QEMU_CAPS_LOCK_LED
? 1 : 0;
1715 num
= ledstate
& QEMU_NUM_LOCK_LED
? 1 : 0;
1716 scr
= ledstate
& QEMU_SCROLL_LOCK_LED
? 1 : 0;
1718 if (vs
->modifiers_state
[0x3a] != caps
) {
1719 vs
->modifiers_state
[0x3a] = caps
;
1721 if (vs
->modifiers_state
[0x45] != num
) {
1722 vs
->modifiers_state
[0x45] = num
;
1724 if (vs
->modifiers_state
[0x46] != scr
) {
1725 vs
->modifiers_state
[0x46] = scr
;
1728 /* Sending the current led state message to the client */
1730 vnc_led_state_change(vs
);
1734 static void do_key_event(VncState
*vs
, int down
, int keycode
, int sym
)
1736 /* QEMU console switch */
1738 case 0x2a: /* Left Shift */
1739 case 0x36: /* Right Shift */
1740 case 0x1d: /* Left CTRL */
1741 case 0x9d: /* Right CTRL */
1742 case 0x38: /* Left ALT */
1743 case 0xb8: /* Right ALT */
1745 vs
->modifiers_state
[keycode
] = 1;
1747 vs
->modifiers_state
[keycode
] = 0;
1749 case 0x02 ... 0x0a: /* '1' to '9' keys */
1750 if (vs
->vd
->dcl
.con
== NULL
&&
1751 down
&& vs
->modifiers_state
[0x1d] && vs
->modifiers_state
[0x38]) {
1752 /* Reset the modifiers sent to the current console */
1754 console_select(keycode
- 0x02);
1758 case 0x3a: /* CapsLock */
1759 case 0x45: /* NumLock */
1761 vs
->modifiers_state
[keycode
] ^= 1;
1765 /* Turn off the lock state sync logic if the client support the led
1768 if (down
&& vs
->vd
->lock_key_sync
&&
1769 !vnc_has_feature(vs
, VNC_FEATURE_LED_STATE
) &&
1770 keycode_is_keypad(vs
->vd
->kbd_layout
, keycode
)) {
1771 /* If the numlock state needs to change then simulate an additional
1772 keypress before sending this one. This will happen if the user
1773 toggles numlock away from the VNC window.
1775 if (keysym_is_numlock(vs
->vd
->kbd_layout
, sym
& 0xFFFF)) {
1776 if (!vs
->modifiers_state
[0x45]) {
1777 trace_vnc_key_sync_numlock(true);
1778 vs
->modifiers_state
[0x45] = 1;
1779 press_key(vs
, 0xff7f);
1782 if (vs
->modifiers_state
[0x45]) {
1783 trace_vnc_key_sync_numlock(false);
1784 vs
->modifiers_state
[0x45] = 0;
1785 press_key(vs
, 0xff7f);
1790 if (down
&& vs
->vd
->lock_key_sync
&&
1791 !vnc_has_feature(vs
, VNC_FEATURE_LED_STATE
) &&
1792 ((sym
>= 'A' && sym
<= 'Z') || (sym
>= 'a' && sym
<= 'z'))) {
1793 /* If the capslock state needs to change then simulate an additional
1794 keypress before sending this one. This will happen if the user
1795 toggles capslock away from the VNC window.
1797 int uppercase
= !!(sym
>= 'A' && sym
<= 'Z');
1798 int shift
= !!(vs
->modifiers_state
[0x2a] | vs
->modifiers_state
[0x36]);
1799 int capslock
= !!(vs
->modifiers_state
[0x3a]);
1801 if (uppercase
== shift
) {
1802 trace_vnc_key_sync_capslock(false);
1803 vs
->modifiers_state
[0x3a] = 0;
1804 press_key(vs
, 0xffe5);
1807 if (uppercase
!= shift
) {
1808 trace_vnc_key_sync_capslock(true);
1809 vs
->modifiers_state
[0x3a] = 1;
1810 press_key(vs
, 0xffe5);
1815 if (qemu_console_is_graphic(NULL
)) {
1816 qemu_input_event_send_key_number(vs
->vd
->dcl
.con
, keycode
, down
);
1817 qemu_input_event_send_key_delay(vs
->vd
->key_delay_ms
);
1819 bool numlock
= vs
->modifiers_state
[0x45];
1820 bool control
= (vs
->modifiers_state
[0x1d] ||
1821 vs
->modifiers_state
[0x9d]);
1822 /* QEMU console emulation */
1825 case 0x2a: /* Left Shift */
1826 case 0x36: /* Right Shift */
1827 case 0x1d: /* Left CTRL */
1828 case 0x9d: /* Right CTRL */
1829 case 0x38: /* Left ALT */
1830 case 0xb8: /* Right ALT */
1833 kbd_put_keysym(QEMU_KEY_UP
);
1836 kbd_put_keysym(QEMU_KEY_DOWN
);
1839 kbd_put_keysym(QEMU_KEY_LEFT
);
1842 kbd_put_keysym(QEMU_KEY_RIGHT
);
1845 kbd_put_keysym(QEMU_KEY_DELETE
);
1848 kbd_put_keysym(QEMU_KEY_HOME
);
1851 kbd_put_keysym(QEMU_KEY_END
);
1854 kbd_put_keysym(QEMU_KEY_PAGEUP
);
1857 kbd_put_keysym(QEMU_KEY_PAGEDOWN
);
1861 kbd_put_keysym(numlock
? '7' : QEMU_KEY_HOME
);
1864 kbd_put_keysym(numlock
? '8' : QEMU_KEY_UP
);
1867 kbd_put_keysym(numlock
? '9' : QEMU_KEY_PAGEUP
);
1870 kbd_put_keysym(numlock
? '4' : QEMU_KEY_LEFT
);
1873 kbd_put_keysym('5');
1876 kbd_put_keysym(numlock
? '6' : QEMU_KEY_RIGHT
);
1879 kbd_put_keysym(numlock
? '1' : QEMU_KEY_END
);
1882 kbd_put_keysym(numlock
? '2' : QEMU_KEY_DOWN
);
1885 kbd_put_keysym(numlock
? '3' : QEMU_KEY_PAGEDOWN
);
1888 kbd_put_keysym('0');
1891 kbd_put_keysym(numlock
? '.' : QEMU_KEY_DELETE
);
1895 kbd_put_keysym('/');
1898 kbd_put_keysym('*');
1901 kbd_put_keysym('-');
1904 kbd_put_keysym('+');
1907 kbd_put_keysym('\n');
1912 kbd_put_keysym(sym
& 0x1f);
1914 kbd_put_keysym(sym
);
1922 static void vnc_release_modifiers(VncState
*vs
)
1924 static const int keycodes
[] = {
1925 /* shift, control, alt keys, both left & right */
1926 0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8,
1930 if (!qemu_console_is_graphic(NULL
)) {
1933 for (i
= 0; i
< ARRAY_SIZE(keycodes
); i
++) {
1934 keycode
= keycodes
[i
];
1935 if (!vs
->modifiers_state
[keycode
]) {
1938 qemu_input_event_send_key_number(vs
->vd
->dcl
.con
, keycode
, false);
1939 qemu_input_event_send_key_delay(vs
->vd
->key_delay_ms
);
1943 static const char *code2name(int keycode
)
1945 return QKeyCode_lookup
[qemu_input_key_number_to_qcode(keycode
)];
1948 static void key_event(VncState
*vs
, int down
, uint32_t sym
)
1953 if (lsym
>= 'A' && lsym
<= 'Z' && qemu_console_is_graphic(NULL
)) {
1954 lsym
= lsym
- 'A' + 'a';
1957 keycode
= keysym2scancode(vs
->vd
->kbd_layout
, lsym
& 0xFFFF) & SCANCODE_KEYMASK
;
1958 trace_vnc_key_event_map(down
, sym
, keycode
, code2name(keycode
));
1959 do_key_event(vs
, down
, keycode
, sym
);
1962 static void ext_key_event(VncState
*vs
, int down
,
1963 uint32_t sym
, uint16_t keycode
)
1965 /* if the user specifies a keyboard layout, always use it */
1966 if (keyboard_layout
) {
1967 key_event(vs
, down
, sym
);
1969 trace_vnc_key_event_ext(down
, sym
, keycode
, code2name(keycode
));
1970 do_key_event(vs
, down
, keycode
, sym
);
1974 static void framebuffer_update_request(VncState
*vs
, int incremental
,
1975 int x
, int y
, int w
, int h
)
1977 vs
->need_update
= 1;
1983 vs
->force_update
= 1;
1984 vnc_set_area_dirty(vs
->dirty
, vs
->vd
, x
, y
, w
, h
);
1987 static void send_ext_key_event_ack(VncState
*vs
)
1989 vnc_lock_output(vs
);
1990 vnc_write_u8(vs
, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE
);
1991 vnc_write_u8(vs
, 0);
1992 vnc_write_u16(vs
, 1);
1993 vnc_framebuffer_update(vs
, 0, 0,
1994 pixman_image_get_width(vs
->vd
->server
),
1995 pixman_image_get_height(vs
->vd
->server
),
1996 VNC_ENCODING_EXT_KEY_EVENT
);
1997 vnc_unlock_output(vs
);
2001 static void send_ext_audio_ack(VncState
*vs
)
2003 vnc_lock_output(vs
);
2004 vnc_write_u8(vs
, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE
);
2005 vnc_write_u8(vs
, 0);
2006 vnc_write_u16(vs
, 1);
2007 vnc_framebuffer_update(vs
, 0, 0,
2008 pixman_image_get_width(vs
->vd
->server
),
2009 pixman_image_get_height(vs
->vd
->server
),
2010 VNC_ENCODING_AUDIO
);
2011 vnc_unlock_output(vs
);
2015 static void set_encodings(VncState
*vs
, int32_t *encodings
, size_t n_encodings
)
2018 unsigned int enc
= 0;
2021 vs
->vnc_encoding
= 0;
2022 vs
->tight
.compression
= 9;
2023 vs
->tight
.quality
= -1; /* Lossless by default */
2027 * Start from the end because the encodings are sent in order of preference.
2028 * This way the preferred encoding (first encoding defined in the array)
2029 * will be set at the end of the loop.
2031 for (i
= n_encodings
- 1; i
>= 0; i
--) {
2034 case VNC_ENCODING_RAW
:
2035 vs
->vnc_encoding
= enc
;
2037 case VNC_ENCODING_COPYRECT
:
2038 vs
->features
|= VNC_FEATURE_COPYRECT_MASK
;
2040 case VNC_ENCODING_HEXTILE
:
2041 vs
->features
|= VNC_FEATURE_HEXTILE_MASK
;
2042 vs
->vnc_encoding
= enc
;
2044 case VNC_ENCODING_TIGHT
:
2045 vs
->features
|= VNC_FEATURE_TIGHT_MASK
;
2046 vs
->vnc_encoding
= enc
;
2048 #ifdef CONFIG_VNC_PNG
2049 case VNC_ENCODING_TIGHT_PNG
:
2050 vs
->features
|= VNC_FEATURE_TIGHT_PNG_MASK
;
2051 vs
->vnc_encoding
= enc
;
2054 case VNC_ENCODING_ZLIB
:
2055 vs
->features
|= VNC_FEATURE_ZLIB_MASK
;
2056 vs
->vnc_encoding
= enc
;
2058 case VNC_ENCODING_ZRLE
:
2059 vs
->features
|= VNC_FEATURE_ZRLE_MASK
;
2060 vs
->vnc_encoding
= enc
;
2062 case VNC_ENCODING_ZYWRLE
:
2063 vs
->features
|= VNC_FEATURE_ZYWRLE_MASK
;
2064 vs
->vnc_encoding
= enc
;
2066 case VNC_ENCODING_DESKTOPRESIZE
:
2067 vs
->features
|= VNC_FEATURE_RESIZE_MASK
;
2069 case VNC_ENCODING_POINTER_TYPE_CHANGE
:
2070 vs
->features
|= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK
;
2072 case VNC_ENCODING_RICH_CURSOR
:
2073 vs
->features
|= VNC_FEATURE_RICH_CURSOR_MASK
;
2074 if (vs
->vd
->cursor
) {
2075 vnc_cursor_define(vs
);
2078 case VNC_ENCODING_EXT_KEY_EVENT
:
2079 send_ext_key_event_ack(vs
);
2081 case VNC_ENCODING_AUDIO
:
2082 send_ext_audio_ack(vs
);
2084 case VNC_ENCODING_WMVi
:
2085 vs
->features
|= VNC_FEATURE_WMVI_MASK
;
2087 case VNC_ENCODING_LED_STATE
:
2088 vs
->features
|= VNC_FEATURE_LED_STATE_MASK
;
2090 case VNC_ENCODING_COMPRESSLEVEL0
... VNC_ENCODING_COMPRESSLEVEL0
+ 9:
2091 vs
->tight
.compression
= (enc
& 0x0F);
2093 case VNC_ENCODING_QUALITYLEVEL0
... VNC_ENCODING_QUALITYLEVEL0
+ 9:
2094 if (vs
->vd
->lossy
) {
2095 vs
->tight
.quality
= (enc
& 0x0F);
2099 VNC_DEBUG("Unknown encoding: %d (0x%.8x): %d\n", i
, enc
, enc
);
2103 vnc_desktop_resize(vs
);
2104 check_pointer_type_change(&vs
->mouse_mode_notifier
, NULL
);
2105 vnc_led_state_change(vs
);
2108 static void set_pixel_conversion(VncState
*vs
)
2110 pixman_format_code_t fmt
= qemu_pixman_get_format(&vs
->client_pf
);
2112 if (fmt
== VNC_SERVER_FB_FORMAT
) {
2113 vs
->write_pixels
= vnc_write_pixels_copy
;
2114 vnc_hextile_set_pixel_conversion(vs
, 0);
2116 vs
->write_pixels
= vnc_write_pixels_generic
;
2117 vnc_hextile_set_pixel_conversion(vs
, 1);
2121 static void send_color_map(VncState
*vs
)
2125 vnc_write_u8(vs
, VNC_MSG_SERVER_SET_COLOUR_MAP_ENTRIES
);
2126 vnc_write_u8(vs
, 0); /* padding */
2127 vnc_write_u16(vs
, 0); /* first color */
2128 vnc_write_u16(vs
, 256); /* # of colors */
2130 for (i
= 0; i
< 256; i
++) {
2131 PixelFormat
*pf
= &vs
->client_pf
;
2133 vnc_write_u16(vs
, (((i
>> pf
->rshift
) & pf
->rmax
) << (16 - pf
->rbits
)));
2134 vnc_write_u16(vs
, (((i
>> pf
->gshift
) & pf
->gmax
) << (16 - pf
->gbits
)));
2135 vnc_write_u16(vs
, (((i
>> pf
->bshift
) & pf
->bmax
) << (16 - pf
->bbits
)));
2139 static void set_pixel_format(VncState
*vs
, int bits_per_pixel
,
2140 int big_endian_flag
, int true_color_flag
,
2141 int red_max
, int green_max
, int blue_max
,
2142 int red_shift
, int green_shift
, int blue_shift
)
2144 if (!true_color_flag
) {
2145 /* Expose a reasonable default 256 color map */
2155 switch (bits_per_pixel
) {
2161 vnc_client_error(vs
);
2165 vs
->client_pf
.rmax
= red_max
? red_max
: 0xFF;
2166 vs
->client_pf
.rbits
= hweight_long(red_max
);
2167 vs
->client_pf
.rshift
= red_shift
;
2168 vs
->client_pf
.rmask
= red_max
<< red_shift
;
2169 vs
->client_pf
.gmax
= green_max
? green_max
: 0xFF;
2170 vs
->client_pf
.gbits
= hweight_long(green_max
);
2171 vs
->client_pf
.gshift
= green_shift
;
2172 vs
->client_pf
.gmask
= green_max
<< green_shift
;
2173 vs
->client_pf
.bmax
= blue_max
? blue_max
: 0xFF;
2174 vs
->client_pf
.bbits
= hweight_long(blue_max
);
2175 vs
->client_pf
.bshift
= blue_shift
;
2176 vs
->client_pf
.bmask
= blue_max
<< blue_shift
;
2177 vs
->client_pf
.bits_per_pixel
= bits_per_pixel
;
2178 vs
->client_pf
.bytes_per_pixel
= bits_per_pixel
/ 8;
2179 vs
->client_pf
.depth
= bits_per_pixel
== 32 ? 24 : bits_per_pixel
;
2180 vs
->client_be
= big_endian_flag
;
2182 if (!true_color_flag
) {
2186 set_pixel_conversion(vs
);
2188 graphic_hw_invalidate(vs
->vd
->dcl
.con
);
2189 graphic_hw_update(vs
->vd
->dcl
.con
);
2192 static void pixel_format_message (VncState
*vs
) {
2193 char pad
[3] = { 0, 0, 0 };
2195 vs
->client_pf
= qemu_default_pixelformat(32);
2197 vnc_write_u8(vs
, vs
->client_pf
.bits_per_pixel
); /* bits-per-pixel */
2198 vnc_write_u8(vs
, vs
->client_pf
.depth
); /* depth */
2200 #ifdef HOST_WORDS_BIGENDIAN
2201 vnc_write_u8(vs
, 1); /* big-endian-flag */
2203 vnc_write_u8(vs
, 0); /* big-endian-flag */
2205 vnc_write_u8(vs
, 1); /* true-color-flag */
2206 vnc_write_u16(vs
, vs
->client_pf
.rmax
); /* red-max */
2207 vnc_write_u16(vs
, vs
->client_pf
.gmax
); /* green-max */
2208 vnc_write_u16(vs
, vs
->client_pf
.bmax
); /* blue-max */
2209 vnc_write_u8(vs
, vs
->client_pf
.rshift
); /* red-shift */
2210 vnc_write_u8(vs
, vs
->client_pf
.gshift
); /* green-shift */
2211 vnc_write_u8(vs
, vs
->client_pf
.bshift
); /* blue-shift */
2212 vnc_write(vs
, pad
, 3); /* padding */
2214 vnc_hextile_set_pixel_conversion(vs
, 0);
2215 vs
->write_pixels
= vnc_write_pixels_copy
;
2218 static void vnc_colordepth(VncState
*vs
)
2220 if (vnc_has_feature(vs
, VNC_FEATURE_WMVI
)) {
2221 /* Sending a WMVi message to notify the client*/
2222 vnc_lock_output(vs
);
2223 vnc_write_u8(vs
, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE
);
2224 vnc_write_u8(vs
, 0);
2225 vnc_write_u16(vs
, 1); /* number of rects */
2226 vnc_framebuffer_update(vs
, 0, 0,
2227 pixman_image_get_width(vs
->vd
->server
),
2228 pixman_image_get_height(vs
->vd
->server
),
2230 pixel_format_message(vs
);
2231 vnc_unlock_output(vs
);
2234 set_pixel_conversion(vs
);
2238 static int protocol_client_msg(VncState
*vs
, uint8_t *data
, size_t len
)
2242 VncDisplay
*vd
= vs
->vd
;
2245 update_displaychangelistener(&vd
->dcl
, VNC_REFRESH_INTERVAL_BASE
);
2249 case VNC_MSG_CLIENT_SET_PIXEL_FORMAT
:
2253 set_pixel_format(vs
, read_u8(data
, 4),
2254 read_u8(data
, 6), read_u8(data
, 7),
2255 read_u16(data
, 8), read_u16(data
, 10),
2256 read_u16(data
, 12), read_u8(data
, 14),
2257 read_u8(data
, 15), read_u8(data
, 16));
2259 case VNC_MSG_CLIENT_SET_ENCODINGS
:
2264 limit
= read_u16(data
, 2);
2266 return 4 + (limit
* 4);
2268 limit
= read_u16(data
, 2);
2270 for (i
= 0; i
< limit
; i
++) {
2271 int32_t val
= read_s32(data
, 4 + (i
* 4));
2272 memcpy(data
+ 4 + (i
* 4), &val
, sizeof(val
));
2275 set_encodings(vs
, (int32_t *)(data
+ 4), limit
);
2277 case VNC_MSG_CLIENT_FRAMEBUFFER_UPDATE_REQUEST
:
2281 framebuffer_update_request(vs
,
2282 read_u8(data
, 1), read_u16(data
, 2), read_u16(data
, 4),
2283 read_u16(data
, 6), read_u16(data
, 8));
2285 case VNC_MSG_CLIENT_KEY_EVENT
:
2289 key_event(vs
, read_u8(data
, 1), read_u32(data
, 4));
2291 case VNC_MSG_CLIENT_POINTER_EVENT
:
2295 pointer_event(vs
, read_u8(data
, 1), read_u16(data
, 2), read_u16(data
, 4));
2297 case VNC_MSG_CLIENT_CUT_TEXT
:
2302 uint32_t dlen
= read_u32(data
, 4);
2303 if (dlen
> (1 << 20)) {
2304 error_report("vnc: client_cut_text msg payload has %u bytes"
2305 " which exceeds our limit of 1MB.", dlen
);
2306 vnc_client_error(vs
);
2314 client_cut_text(vs
, read_u32(data
, 4), data
+ 8);
2316 case VNC_MSG_CLIENT_QEMU
:
2320 switch (read_u8(data
, 1)) {
2321 case VNC_MSG_CLIENT_QEMU_EXT_KEY_EVENT
:
2325 ext_key_event(vs
, read_u16(data
, 2),
2326 read_u32(data
, 4), read_u32(data
, 8));
2328 case VNC_MSG_CLIENT_QEMU_AUDIO
:
2332 switch (read_u16 (data
, 2)) {
2333 case VNC_MSG_CLIENT_QEMU_AUDIO_ENABLE
:
2336 case VNC_MSG_CLIENT_QEMU_AUDIO_DISABLE
:
2339 case VNC_MSG_CLIENT_QEMU_AUDIO_SET_FORMAT
:
2342 switch (read_u8(data
, 4)) {
2343 case 0: vs
->as
.fmt
= AUD_FMT_U8
; break;
2344 case 1: vs
->as
.fmt
= AUD_FMT_S8
; break;
2345 case 2: vs
->as
.fmt
= AUD_FMT_U16
; break;
2346 case 3: vs
->as
.fmt
= AUD_FMT_S16
; break;
2347 case 4: vs
->as
.fmt
= AUD_FMT_U32
; break;
2348 case 5: vs
->as
.fmt
= AUD_FMT_S32
; break;
2350 VNC_DEBUG("Invalid audio format %d\n", read_u8(data
, 4));
2351 vnc_client_error(vs
);
2354 vs
->as
.nchannels
= read_u8(data
, 5);
2355 if (vs
->as
.nchannels
!= 1 && vs
->as
.nchannels
!= 2) {
2356 VNC_DEBUG("Invalid audio channel coount %d\n",
2358 vnc_client_error(vs
);
2361 vs
->as
.freq
= read_u32(data
, 6);
2364 VNC_DEBUG("Invalid audio message %d\n", read_u8(data
, 4));
2365 vnc_client_error(vs
);
2371 VNC_DEBUG("Msg: %d\n", read_u16(data
, 0));
2372 vnc_client_error(vs
);
2377 VNC_DEBUG("Msg: %d\n", data
[0]);
2378 vnc_client_error(vs
);
2382 vnc_read_when(vs
, protocol_client_msg
, 1);
2386 static int protocol_client_init(VncState
*vs
, uint8_t *data
, size_t len
)
2392 mode
= data
[0] ? VNC_SHARE_MODE_SHARED
: VNC_SHARE_MODE_EXCLUSIVE
;
2393 switch (vs
->vd
->share_policy
) {
2394 case VNC_SHARE_POLICY_IGNORE
:
2396 * Ignore the shared flag. Nothing to do here.
2398 * Doesn't conform to the rfb spec but is traditional qemu
2399 * behavior, thus left here as option for compatibility
2403 case VNC_SHARE_POLICY_ALLOW_EXCLUSIVE
:
2405 * Policy: Allow clients ask for exclusive access.
2407 * Implementation: When a client asks for exclusive access,
2408 * disconnect all others. Shared connects are allowed as long
2409 * as no exclusive connection exists.
2411 * This is how the rfb spec suggests to handle the shared flag.
2413 if (mode
== VNC_SHARE_MODE_EXCLUSIVE
) {
2415 QTAILQ_FOREACH(client
, &vs
->vd
->clients
, next
) {
2419 if (client
->share_mode
!= VNC_SHARE_MODE_EXCLUSIVE
&&
2420 client
->share_mode
!= VNC_SHARE_MODE_SHARED
) {
2423 vnc_disconnect_start(client
);
2426 if (mode
== VNC_SHARE_MODE_SHARED
) {
2427 if (vs
->vd
->num_exclusive
> 0) {
2428 vnc_disconnect_start(vs
);
2433 case VNC_SHARE_POLICY_FORCE_SHARED
:
2435 * Policy: Shared connects only.
2436 * Implementation: Disallow clients asking for exclusive access.
2438 * Useful for shared desktop sessions where you don't want
2439 * someone forgetting to say -shared when running the vnc
2440 * client disconnect everybody else.
2442 if (mode
== VNC_SHARE_MODE_EXCLUSIVE
) {
2443 vnc_disconnect_start(vs
);
2448 vnc_set_share_mode(vs
, mode
);
2450 if (vs
->vd
->num_shared
> vs
->vd
->connections_limit
) {
2451 vnc_disconnect_start(vs
);
2455 vs
->client_width
= pixman_image_get_width(vs
->vd
->server
);
2456 vs
->client_height
= pixman_image_get_height(vs
->vd
->server
);
2457 vnc_write_u16(vs
, vs
->client_width
);
2458 vnc_write_u16(vs
, vs
->client_height
);
2460 pixel_format_message(vs
);
2463 size
= snprintf(buf
, sizeof(buf
), "QEMU (%s)", qemu_name
);
2465 size
= snprintf(buf
, sizeof(buf
), "QEMU");
2467 vnc_write_u32(vs
, size
);
2468 vnc_write(vs
, buf
, size
);
2471 vnc_client_cache_auth(vs
);
2472 vnc_qmp_event(vs
, QAPI_EVENT_VNC_INITIALIZED
);
2474 vnc_read_when(vs
, protocol_client_msg
, 1);
2479 void start_client_init(VncState
*vs
)
2481 vnc_read_when(vs
, protocol_client_init
, 1);
2484 static void make_challenge(VncState
*vs
)
2488 srand(time(NULL
)+getpid()+getpid()*987654+rand());
2490 for (i
= 0 ; i
< sizeof(vs
->challenge
) ; i
++)
2491 vs
->challenge
[i
] = (int) (256.0*rand()/(RAND_MAX
+1.0));
2494 static int protocol_client_auth_vnc(VncState
*vs
, uint8_t *data
, size_t len
)
2496 unsigned char response
[VNC_AUTH_CHALLENGE_SIZE
];
2498 unsigned char key
[8];
2499 time_t now
= time(NULL
);
2500 QCryptoCipher
*cipher
= NULL
;
2503 if (!vs
->vd
->password
) {
2504 VNC_DEBUG("No password configured on server");
2507 if (vs
->vd
->expires
< now
) {
2508 VNC_DEBUG("Password is expired");
2512 memcpy(response
, vs
->challenge
, VNC_AUTH_CHALLENGE_SIZE
);
2514 /* Calculate the expected challenge response */
2515 pwlen
= strlen(vs
->vd
->password
);
2516 for (i
=0; i
<sizeof(key
); i
++)
2517 key
[i
] = i
<pwlen
? vs
->vd
->password
[i
] : 0;
2519 cipher
= qcrypto_cipher_new(
2520 QCRYPTO_CIPHER_ALG_DES_RFB
,
2521 QCRYPTO_CIPHER_MODE_ECB
,
2522 key
, G_N_ELEMENTS(key
),
2525 VNC_DEBUG("Cannot initialize cipher %s",
2526 error_get_pretty(err
));
2531 if (qcrypto_cipher_encrypt(cipher
,
2534 VNC_AUTH_CHALLENGE_SIZE
,
2536 VNC_DEBUG("Cannot encrypt challenge %s",
2537 error_get_pretty(err
));
2542 /* Compare expected vs actual challenge response */
2543 if (memcmp(response
, data
, VNC_AUTH_CHALLENGE_SIZE
) != 0) {
2544 VNC_DEBUG("Client challenge response did not match\n");
2547 VNC_DEBUG("Accepting VNC challenge response\n");
2548 vnc_write_u32(vs
, 0); /* Accept auth */
2551 start_client_init(vs
);
2554 qcrypto_cipher_free(cipher
);
2558 vnc_write_u32(vs
, 1); /* Reject auth */
2559 if (vs
->minor
>= 8) {
2560 static const char err
[] = "Authentication failed";
2561 vnc_write_u32(vs
, sizeof(err
));
2562 vnc_write(vs
, err
, sizeof(err
));
2565 vnc_client_error(vs
);
2566 qcrypto_cipher_free(cipher
);
2570 void start_auth_vnc(VncState
*vs
)
2573 /* Send client a 'random' challenge */
2574 vnc_write(vs
, vs
->challenge
, sizeof(vs
->challenge
));
2577 vnc_read_when(vs
, protocol_client_auth_vnc
, sizeof(vs
->challenge
));
2581 static int protocol_client_auth(VncState
*vs
, uint8_t *data
, size_t len
)
2583 /* We only advertise 1 auth scheme at a time, so client
2584 * must pick the one we sent. Verify this */
2585 if (data
[0] != vs
->auth
) { /* Reject auth */
2586 VNC_DEBUG("Reject auth %d because it didn't match advertized\n", (int)data
[0]);
2587 vnc_write_u32(vs
, 1);
2588 if (vs
->minor
>= 8) {
2589 static const char err
[] = "Authentication failed";
2590 vnc_write_u32(vs
, sizeof(err
));
2591 vnc_write(vs
, err
, sizeof(err
));
2593 vnc_client_error(vs
);
2594 } else { /* Accept requested auth */
2595 VNC_DEBUG("Client requested auth %d\n", (int)data
[0]);
2598 VNC_DEBUG("Accept auth none\n");
2599 if (vs
->minor
>= 8) {
2600 vnc_write_u32(vs
, 0); /* Accept auth completion */
2603 start_client_init(vs
);
2607 VNC_DEBUG("Start VNC auth\n");
2611 case VNC_AUTH_VENCRYPT
:
2612 VNC_DEBUG("Accept VeNCrypt auth\n");
2613 start_auth_vencrypt(vs
);
2616 #ifdef CONFIG_VNC_SASL
2618 VNC_DEBUG("Accept SASL auth\n");
2619 start_auth_sasl(vs
);
2621 #endif /* CONFIG_VNC_SASL */
2623 default: /* Should not be possible, but just in case */
2624 VNC_DEBUG("Reject auth %d server code bug\n", vs
->auth
);
2625 vnc_write_u8(vs
, 1);
2626 if (vs
->minor
>= 8) {
2627 static const char err
[] = "Authentication failed";
2628 vnc_write_u32(vs
, sizeof(err
));
2629 vnc_write(vs
, err
, sizeof(err
));
2631 vnc_client_error(vs
);
2637 static int protocol_version(VncState
*vs
, uint8_t *version
, size_t len
)
2641 memcpy(local
, version
, 12);
2644 if (sscanf(local
, "RFB %03d.%03d\n", &vs
->major
, &vs
->minor
) != 2) {
2645 VNC_DEBUG("Malformed protocol version %s\n", local
);
2646 vnc_client_error(vs
);
2649 VNC_DEBUG("Client request protocol version %d.%d\n", vs
->major
, vs
->minor
);
2650 if (vs
->major
!= 3 ||
2656 VNC_DEBUG("Unsupported client version\n");
2657 vnc_write_u32(vs
, VNC_AUTH_INVALID
);
2659 vnc_client_error(vs
);
2662 /* Some broken clients report v3.4 or v3.5, which spec requires to be treated
2663 * as equivalent to v3.3 by servers
2665 if (vs
->minor
== 4 || vs
->minor
== 5)
2668 if (vs
->minor
== 3) {
2669 if (vs
->auth
== VNC_AUTH_NONE
) {
2670 VNC_DEBUG("Tell client auth none\n");
2671 vnc_write_u32(vs
, vs
->auth
);
2673 start_client_init(vs
);
2674 } else if (vs
->auth
== VNC_AUTH_VNC
) {
2675 VNC_DEBUG("Tell client VNC auth\n");
2676 vnc_write_u32(vs
, vs
->auth
);
2680 VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs
->auth
);
2681 vnc_write_u32(vs
, VNC_AUTH_INVALID
);
2683 vnc_client_error(vs
);
2686 VNC_DEBUG("Telling client we support auth %d\n", vs
->auth
);
2687 vnc_write_u8(vs
, 1); /* num auth */
2688 vnc_write_u8(vs
, vs
->auth
);
2689 vnc_read_when(vs
, protocol_client_auth
, 1);
2696 static VncRectStat
*vnc_stat_rect(VncDisplay
*vd
, int x
, int y
)
2698 struct VncSurface
*vs
= &vd
->guest
;
2700 return &vs
->stats
[y
/ VNC_STAT_RECT
][x
/ VNC_STAT_RECT
];
2703 void vnc_sent_lossy_rect(VncState
*vs
, int x
, int y
, int w
, int h
)
2707 w
= (x
+ w
) / VNC_STAT_RECT
;
2708 h
= (y
+ h
) / VNC_STAT_RECT
;
2712 for (j
= y
; j
<= h
; j
++) {
2713 for (i
= x
; i
<= w
; i
++) {
2714 vs
->lossy_rect
[j
][i
] = 1;
2719 static int vnc_refresh_lossy_rect(VncDisplay
*vd
, int x
, int y
)
2722 int sty
= y
/ VNC_STAT_RECT
;
2723 int stx
= x
/ VNC_STAT_RECT
;
2726 y
= y
/ VNC_STAT_RECT
* VNC_STAT_RECT
;
2727 x
= x
/ VNC_STAT_RECT
* VNC_STAT_RECT
;
2729 QTAILQ_FOREACH(vs
, &vd
->clients
, next
) {
2732 /* kernel send buffers are full -> refresh later */
2733 if (vs
->output
.offset
) {
2737 if (!vs
->lossy_rect
[sty
][stx
]) {
2741 vs
->lossy_rect
[sty
][stx
] = 0;
2742 for (j
= 0; j
< VNC_STAT_RECT
; ++j
) {
2743 bitmap_set(vs
->dirty
[y
+ j
],
2744 x
/ VNC_DIRTY_PIXELS_PER_BIT
,
2745 VNC_STAT_RECT
/ VNC_DIRTY_PIXELS_PER_BIT
);
2753 static int vnc_update_stats(VncDisplay
*vd
, struct timeval
* tv
)
2755 int width
= pixman_image_get_width(vd
->guest
.fb
);
2756 int height
= pixman_image_get_height(vd
->guest
.fb
);
2761 for (y
= 0; y
< height
; y
+= VNC_STAT_RECT
) {
2762 for (x
= 0; x
< width
; x
+= VNC_STAT_RECT
) {
2763 VncRectStat
*rect
= vnc_stat_rect(vd
, x
, y
);
2765 rect
->updated
= false;
2769 qemu_timersub(tv
, &VNC_REFRESH_STATS
, &res
);
2771 if (timercmp(&vd
->guest
.last_freq_check
, &res
, >)) {
2774 vd
->guest
.last_freq_check
= *tv
;
2776 for (y
= 0; y
< height
; y
+= VNC_STAT_RECT
) {
2777 for (x
= 0; x
< width
; x
+= VNC_STAT_RECT
) {
2778 VncRectStat
*rect
= vnc_stat_rect(vd
, x
, y
);
2779 int count
= ARRAY_SIZE(rect
->times
);
2780 struct timeval min
, max
;
2782 if (!timerisset(&rect
->times
[count
- 1])) {
2786 max
= rect
->times
[(rect
->idx
+ count
- 1) % count
];
2787 qemu_timersub(tv
, &max
, &res
);
2789 if (timercmp(&res
, &VNC_REFRESH_LOSSY
, >)) {
2791 has_dirty
+= vnc_refresh_lossy_rect(vd
, x
, y
);
2792 memset(rect
->times
, 0, sizeof (rect
->times
));
2796 min
= rect
->times
[rect
->idx
];
2797 max
= rect
->times
[(rect
->idx
+ count
- 1) % count
];
2798 qemu_timersub(&max
, &min
, &res
);
2800 rect
->freq
= res
.tv_sec
+ res
.tv_usec
/ 1000000.;
2801 rect
->freq
/= count
;
2802 rect
->freq
= 1. / rect
->freq
;
2808 double vnc_update_freq(VncState
*vs
, int x
, int y
, int w
, int h
)
2814 x
= (x
/ VNC_STAT_RECT
) * VNC_STAT_RECT
;
2815 y
= (y
/ VNC_STAT_RECT
) * VNC_STAT_RECT
;
2817 for (j
= y
; j
<= y
+ h
; j
+= VNC_STAT_RECT
) {
2818 for (i
= x
; i
<= x
+ w
; i
+= VNC_STAT_RECT
) {
2819 total
+= vnc_stat_rect(vs
->vd
, i
, j
)->freq
;
2831 static void vnc_rect_updated(VncDisplay
*vd
, int x
, int y
, struct timeval
* tv
)
2835 rect
= vnc_stat_rect(vd
, x
, y
);
2836 if (rect
->updated
) {
2839 rect
->times
[rect
->idx
] = *tv
;
2840 rect
->idx
= (rect
->idx
+ 1) % ARRAY_SIZE(rect
->times
);
2841 rect
->updated
= true;
2844 static int vnc_refresh_server_surface(VncDisplay
*vd
)
2846 int width
= MIN(pixman_image_get_width(vd
->guest
.fb
),
2847 pixman_image_get_width(vd
->server
));
2848 int height
= MIN(pixman_image_get_height(vd
->guest
.fb
),
2849 pixman_image_get_height(vd
->server
));
2850 int cmp_bytes
, server_stride
, line_bytes
, guest_ll
, guest_stride
, y
= 0;
2851 uint8_t *guest_row0
= NULL
, *server_row0
;
2854 pixman_image_t
*tmpbuf
= NULL
;
2856 struct timeval tv
= { 0, 0 };
2858 if (!vd
->non_adaptive
) {
2859 gettimeofday(&tv
, NULL
);
2860 has_dirty
= vnc_update_stats(vd
, &tv
);
2864 * Walk through the guest dirty map.
2865 * Check and copy modified bits from guest to server surface.
2866 * Update server dirty map.
2868 server_row0
= (uint8_t *)pixman_image_get_data(vd
->server
);
2869 server_stride
= guest_stride
= guest_ll
=
2870 pixman_image_get_stride(vd
->server
);
2871 cmp_bytes
= MIN(VNC_DIRTY_PIXELS_PER_BIT
* VNC_SERVER_FB_BYTES
,
2873 if (vd
->guest
.format
!= VNC_SERVER_FB_FORMAT
) {
2874 int width
= pixman_image_get_width(vd
->server
);
2875 tmpbuf
= qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT
, width
);
2878 PIXMAN_FORMAT_BPP(pixman_image_get_format(vd
->guest
.fb
));
2879 guest_row0
= (uint8_t *)pixman_image_get_data(vd
->guest
.fb
);
2880 guest_stride
= pixman_image_get_stride(vd
->guest
.fb
);
2881 guest_ll
= pixman_image_get_width(vd
->guest
.fb
) * ((guest_bpp
+ 7) / 8);
2883 line_bytes
= MIN(server_stride
, guest_ll
);
2887 uint8_t *guest_ptr
, *server_ptr
;
2888 unsigned long offset
= find_next_bit((unsigned long *) &vd
->guest
.dirty
,
2889 height
* VNC_DIRTY_BPL(&vd
->guest
),
2890 y
* VNC_DIRTY_BPL(&vd
->guest
));
2891 if (offset
== height
* VNC_DIRTY_BPL(&vd
->guest
)) {
2892 /* no more dirty bits */
2895 y
= offset
/ VNC_DIRTY_BPL(&vd
->guest
);
2896 x
= offset
% VNC_DIRTY_BPL(&vd
->guest
);
2898 server_ptr
= server_row0
+ y
* server_stride
+ x
* cmp_bytes
;
2900 if (vd
->guest
.format
!= VNC_SERVER_FB_FORMAT
) {
2901 qemu_pixman_linebuf_fill(tmpbuf
, vd
->guest
.fb
, width
, 0, y
);
2902 guest_ptr
= (uint8_t *)pixman_image_get_data(tmpbuf
);
2904 guest_ptr
= guest_row0
+ y
* guest_stride
;
2906 guest_ptr
+= x
* cmp_bytes
;
2908 for (; x
< DIV_ROUND_UP(width
, VNC_DIRTY_PIXELS_PER_BIT
);
2909 x
++, guest_ptr
+= cmp_bytes
, server_ptr
+= cmp_bytes
) {
2910 int _cmp_bytes
= cmp_bytes
;
2911 if (!test_and_clear_bit(x
, vd
->guest
.dirty
[y
])) {
2914 if ((x
+ 1) * cmp_bytes
> line_bytes
) {
2915 _cmp_bytes
= line_bytes
- x
* cmp_bytes
;
2917 assert(_cmp_bytes
>= 0);
2918 if (memcmp(server_ptr
, guest_ptr
, _cmp_bytes
) == 0) {
2921 memcpy(server_ptr
, guest_ptr
, _cmp_bytes
);
2922 if (!vd
->non_adaptive
) {
2923 vnc_rect_updated(vd
, x
* VNC_DIRTY_PIXELS_PER_BIT
,
2926 QTAILQ_FOREACH(vs
, &vd
->clients
, next
) {
2927 set_bit(x
, vs
->dirty
[y
]);
2934 qemu_pixman_image_unref(tmpbuf
);
2938 static void vnc_refresh(DisplayChangeListener
*dcl
)
2940 VncDisplay
*vd
= container_of(dcl
, VncDisplay
, dcl
);
2942 int has_dirty
, rects
= 0;
2944 if (QTAILQ_EMPTY(&vd
->clients
)) {
2945 update_displaychangelistener(&vd
->dcl
, VNC_REFRESH_INTERVAL_MAX
);
2949 graphic_hw_update(vd
->dcl
.con
);
2951 if (vnc_trylock_display(vd
)) {
2952 update_displaychangelistener(&vd
->dcl
, VNC_REFRESH_INTERVAL_BASE
);
2956 has_dirty
= vnc_refresh_server_surface(vd
);
2957 vnc_unlock_display(vd
);
2959 QTAILQ_FOREACH_SAFE(vs
, &vd
->clients
, next
, vn
) {
2960 rects
+= vnc_update_client(vs
, has_dirty
, false);
2961 /* vs might be free()ed here */
2964 if (has_dirty
&& rects
) {
2965 vd
->dcl
.update_interval
/= 2;
2966 if (vd
->dcl
.update_interval
< VNC_REFRESH_INTERVAL_BASE
) {
2967 vd
->dcl
.update_interval
= VNC_REFRESH_INTERVAL_BASE
;
2970 vd
->dcl
.update_interval
+= VNC_REFRESH_INTERVAL_INC
;
2971 if (vd
->dcl
.update_interval
> VNC_REFRESH_INTERVAL_MAX
) {
2972 vd
->dcl
.update_interval
= VNC_REFRESH_INTERVAL_MAX
;
2977 static void vnc_connect(VncDisplay
*vd
, QIOChannelSocket
*sioc
,
2978 bool skipauth
, bool websocket
)
2980 VncState
*vs
= g_new0(VncState
, 1);
2981 bool first_client
= QTAILQ_EMPTY(&vd
->clients
);
2985 object_ref(OBJECT(vs
->sioc
));
2986 vs
->ioc
= QIO_CHANNEL(sioc
);
2987 object_ref(OBJECT(vs
->ioc
));
2990 buffer_init(&vs
->input
, "vnc-input/%p", sioc
);
2991 buffer_init(&vs
->output
, "vnc-output/%p", sioc
);
2992 buffer_init(&vs
->jobs_buffer
, "vnc-jobs_buffer/%p", sioc
);
2994 buffer_init(&vs
->tight
.tight
, "vnc-tight/%p", sioc
);
2995 buffer_init(&vs
->tight
.zlib
, "vnc-tight-zlib/%p", sioc
);
2996 buffer_init(&vs
->tight
.gradient
, "vnc-tight-gradient/%p", sioc
);
2997 #ifdef CONFIG_VNC_JPEG
2998 buffer_init(&vs
->tight
.jpeg
, "vnc-tight-jpeg/%p", sioc
);
3000 #ifdef CONFIG_VNC_PNG
3001 buffer_init(&vs
->tight
.png
, "vnc-tight-png/%p", sioc
);
3003 buffer_init(&vs
->zlib
.zlib
, "vnc-zlib/%p", sioc
);
3004 buffer_init(&vs
->zrle
.zrle
, "vnc-zrle/%p", sioc
);
3005 buffer_init(&vs
->zrle
.fb
, "vnc-zrle-fb/%p", sioc
);
3006 buffer_init(&vs
->zrle
.zlib
, "vnc-zrle-zlib/%p", sioc
);
3009 vs
->auth
= VNC_AUTH_NONE
;
3010 vs
->subauth
= VNC_AUTH_INVALID
;
3013 vs
->auth
= vd
->ws_auth
;
3014 vs
->subauth
= VNC_AUTH_INVALID
;
3016 vs
->auth
= vd
->auth
;
3017 vs
->subauth
= vd
->subauth
;
3020 VNC_DEBUG("Client sioc=%p ws=%d auth=%d subauth=%d\n",
3021 sioc
, websocket
, vs
->auth
, vs
->subauth
);
3023 vs
->lossy_rect
= g_malloc0(VNC_STAT_ROWS
* sizeof (*vs
->lossy_rect
));
3024 for (i
= 0; i
< VNC_STAT_ROWS
; ++i
) {
3025 vs
->lossy_rect
[i
] = g_new0(uint8_t, VNC_STAT_COLS
);
3028 VNC_DEBUG("New client on socket %p\n", vs
->sioc
);
3029 update_displaychangelistener(&vd
->dcl
, VNC_REFRESH_INTERVAL_BASE
);
3030 qio_channel_set_blocking(vs
->ioc
, false, NULL
);
3034 vs
->ioc_tag
= qio_channel_add_watch(
3035 vs
->ioc
, G_IO_IN
, vncws_tls_handshake_io
, vs
, NULL
);
3037 vs
->ioc_tag
= qio_channel_add_watch(
3038 vs
->ioc
, G_IO_IN
, vncws_handshake_io
, vs
, NULL
);
3041 vs
->ioc_tag
= qio_channel_add_watch(
3042 vs
->ioc
, G_IO_IN
, vnc_client_io
, vs
, NULL
);
3045 vnc_client_cache_addr(vs
);
3046 vnc_qmp_event(vs
, QAPI_EVENT_VNC_CONNECTED
);
3047 vnc_set_share_mode(vs
, VNC_SHARE_MODE_CONNECTING
);
3052 vs
->as
.freq
= 44100;
3053 vs
->as
.nchannels
= 2;
3054 vs
->as
.fmt
= AUD_FMT_S16
;
3055 vs
->as
.endianness
= 0;
3057 qemu_mutex_init(&vs
->output_mutex
);
3058 vs
->bh
= qemu_bh_new(vnc_jobs_bh
, vs
);
3060 QTAILQ_INSERT_TAIL(&vd
->clients
, vs
, next
);
3062 vnc_update_server_surface(vd
);
3065 graphic_hw_update(vd
->dcl
.con
);
3067 if (!vs
->websocket
) {
3068 vnc_start_protocol(vs
);
3071 if (vd
->num_connecting
> vd
->connections_limit
) {
3072 QTAILQ_FOREACH(vs
, &vd
->clients
, next
) {
3073 if (vs
->share_mode
== VNC_SHARE_MODE_CONNECTING
) {
3074 vnc_disconnect_start(vs
);
3081 void vnc_start_protocol(VncState
*vs
)
3083 vnc_write(vs
, "RFB 003.008\n", 12);
3085 vnc_read_when(vs
, protocol_version
, 12);
3086 if (vs
->vd
->lock_key_sync
)
3087 vs
->led
= qemu_add_led_event_handler(kbd_leds
, vs
);
3089 vs
->mouse_mode_notifier
.notify
= check_pointer_type_change
;
3090 qemu_add_mouse_mode_change_notifier(&vs
->mouse_mode_notifier
);
3093 static gboolean
vnc_listen_io(QIOChannel
*ioc
,
3094 GIOCondition condition
,
3097 VncDisplay
*vd
= opaque
;
3098 QIOChannelSocket
*sioc
= NULL
;
3101 sioc
= qio_channel_socket_accept(QIO_CHANNEL_SOCKET(ioc
), &err
);
3103 qio_channel_set_delay(QIO_CHANNEL(sioc
), false);
3104 vnc_connect(vd
, sioc
, false,
3105 ioc
!= QIO_CHANNEL(vd
->lsock
));
3106 object_unref(OBJECT(sioc
));
3108 /* client probably closed connection before we got there */
3115 static const DisplayChangeListenerOps dcl_ops
= {
3117 .dpy_refresh
= vnc_refresh
,
3118 .dpy_gfx_copy
= vnc_dpy_copy
,
3119 .dpy_gfx_update
= vnc_dpy_update
,
3120 .dpy_gfx_switch
= vnc_dpy_switch
,
3121 .dpy_gfx_check_format
= qemu_pixman_check_format
,
3122 .dpy_mouse_set
= vnc_mouse_set
,
3123 .dpy_cursor_define
= vnc_dpy_cursor_define
,
3126 void vnc_display_init(const char *id
)
3130 if (vnc_display_find(id
) != NULL
) {
3133 vd
= g_malloc0(sizeof(*vd
));
3135 vd
->id
= strdup(id
);
3136 QTAILQ_INSERT_TAIL(&vnc_displays
, vd
, next
);
3138 QTAILQ_INIT(&vd
->clients
);
3139 vd
->expires
= TIME_MAX
;
3141 if (keyboard_layout
) {
3142 trace_vnc_key_map_init(keyboard_layout
);
3143 vd
->kbd_layout
= init_keyboard_layout(name2keysym
, keyboard_layout
);
3145 vd
->kbd_layout
= init_keyboard_layout(name2keysym
, "en-us");
3148 if (!vd
->kbd_layout
) {
3152 vd
->share_policy
= VNC_SHARE_POLICY_ALLOW_EXCLUSIVE
;
3153 vd
->connections_limit
= 32;
3155 qemu_mutex_init(&vd
->mutex
);
3156 vnc_start_worker_thread();
3158 vd
->dcl
.ops
= &dcl_ops
;
3159 register_displaychangelistener(&vd
->dcl
);
3163 static void vnc_display_close(VncDisplay
*vd
)
3168 vd
->is_unix
= false;
3169 if (vd
->lsock
!= NULL
) {
3170 if (vd
->lsock_tag
) {
3171 g_source_remove(vd
->lsock_tag
);
3173 object_unref(OBJECT(vd
->lsock
));
3176 if (vd
->lwebsock
!= NULL
) {
3177 if (vd
->lwebsock_tag
) {
3178 g_source_remove(vd
->lwebsock_tag
);
3180 object_unref(OBJECT(vd
->lwebsock
));
3181 vd
->lwebsock
= NULL
;
3183 vd
->auth
= VNC_AUTH_INVALID
;
3184 vd
->subauth
= VNC_AUTH_INVALID
;
3186 object_unparent(OBJECT(vd
->tlscreds
));
3187 vd
->tlscreds
= NULL
;
3189 g_free(vd
->tlsaclname
);
3190 vd
->tlsaclname
= NULL
;
3193 int vnc_display_password(const char *id
, const char *password
)
3195 VncDisplay
*vd
= vnc_display_find(id
);
3200 if (vd
->auth
== VNC_AUTH_NONE
) {
3201 error_printf_unless_qmp("If you want use passwords please enable "
3202 "password auth using '-vnc ${dpy},password'.\n");
3206 g_free(vd
->password
);
3207 vd
->password
= g_strdup(password
);
3212 int vnc_display_pw_expire(const char *id
, time_t expires
)
3214 VncDisplay
*vd
= vnc_display_find(id
);
3220 vd
->expires
= expires
;
3224 static void vnc_display_print_local_addr(VncDisplay
*vd
)
3226 SocketAddress
*addr
;
3229 addr
= qio_channel_socket_get_local_address(vd
->lsock
, &err
);
3234 if (addr
->type
!= SOCKET_ADDRESS_KIND_INET
) {
3235 qapi_free_SocketAddress(addr
);
3238 error_printf_unless_qmp("VNC server running on %s:%s\n",
3239 addr
->u
.inet
.data
->host
,
3240 addr
->u
.inet
.data
->port
);
3241 qapi_free_SocketAddress(addr
);
3244 static QemuOptsList qemu_vnc_opts
= {
3246 .head
= QTAILQ_HEAD_INITIALIZER(qemu_vnc_opts
.head
),
3247 .implied_opt_name
= "vnc",
3251 .type
= QEMU_OPT_STRING
,
3253 .name
= "websocket",
3254 .type
= QEMU_OPT_STRING
,
3256 .name
= "tls-creds",
3257 .type
= QEMU_OPT_STRING
,
3259 /* Deprecated in favour of tls-creds */
3261 .type
= QEMU_OPT_STRING
,
3264 .type
= QEMU_OPT_STRING
,
3267 .type
= QEMU_OPT_STRING
,
3270 .type
= QEMU_OPT_NUMBER
,
3272 .name
= "connections",
3273 .type
= QEMU_OPT_NUMBER
,
3276 .type
= QEMU_OPT_NUMBER
,
3279 .type
= QEMU_OPT_BOOL
,
3282 .type
= QEMU_OPT_BOOL
,
3285 .type
= QEMU_OPT_BOOL
,
3288 .type
= QEMU_OPT_BOOL
,
3290 .name
= "lock-key-sync",
3291 .type
= QEMU_OPT_BOOL
,
3293 .name
= "key-delay-ms",
3294 .type
= QEMU_OPT_NUMBER
,
3297 .type
= QEMU_OPT_BOOL
,
3299 /* Deprecated in favour of tls-creds */
3301 .type
= QEMU_OPT_BOOL
,
3303 /* Deprecated in favour of tls-creds */
3304 .name
= "x509verify",
3305 .type
= QEMU_OPT_STRING
,
3308 .type
= QEMU_OPT_BOOL
,
3311 .type
= QEMU_OPT_BOOL
,
3313 .name
= "non-adaptive",
3314 .type
= QEMU_OPT_BOOL
,
3316 { /* end of list */ }
3322 vnc_display_setup_auth(int *auth
,
3324 QCryptoTLSCreds
*tlscreds
,
3331 * We have a choice of 3 authentication options
3337 * The channel can be run in 2 modes
3342 * And TLS can use 2 types of credentials
3347 * We thus have 9 possible logical combinations
3352 * 4. tls + anon + none
3353 * 5. tls + anon + vnc
3354 * 6. tls + anon + sasl
3355 * 7. tls + x509 + none
3356 * 8. tls + x509 + vnc
3357 * 9. tls + x509 + sasl
3359 * These need to be mapped into the VNC auth schemes
3360 * in an appropriate manner. In regular VNC, all the
3361 * TLS options get mapped into VNC_AUTH_VENCRYPT
3364 * In websockets, the https:// protocol already provides
3365 * TLS support, so there is no need to make use of the
3366 * VeNCrypt extension. Furthermore, websockets browser
3367 * clients could not use VeNCrypt even if they wanted to,
3368 * as they cannot control when the TLS handshake takes
3369 * place. Thus there is no option but to rely on https://,
3370 * meaning combinations 4->6 and 7->9 will be mapped to
3371 * VNC auth schemes in the same way as combos 1->3.
3373 * Regardless of fact that we have a different mapping to
3374 * VNC auth mechs for plain VNC vs websockets VNC, the end
3375 * result has the same security characteristics.
3377 if (websocket
|| !tlscreds
) {
3379 VNC_DEBUG("Initializing VNC server with password auth\n");
3380 *auth
= VNC_AUTH_VNC
;
3382 VNC_DEBUG("Initializing VNC server with SASL auth\n");
3383 *auth
= VNC_AUTH_SASL
;
3385 VNC_DEBUG("Initializing VNC server with no auth\n");
3386 *auth
= VNC_AUTH_NONE
;
3388 *subauth
= VNC_AUTH_INVALID
;
3390 bool is_x509
= object_dynamic_cast(OBJECT(tlscreds
),
3391 TYPE_QCRYPTO_TLS_CREDS_X509
) != NULL
;
3392 bool is_anon
= object_dynamic_cast(OBJECT(tlscreds
),
3393 TYPE_QCRYPTO_TLS_CREDS_ANON
) != NULL
;
3395 if (!is_x509
&& !is_anon
) {
3397 "Unsupported TLS cred type %s",
3398 object_get_typename(OBJECT(tlscreds
)));
3401 *auth
= VNC_AUTH_VENCRYPT
;
3404 VNC_DEBUG("Initializing VNC server with x509 password auth\n");
3405 *subauth
= VNC_AUTH_VENCRYPT_X509VNC
;
3407 VNC_DEBUG("Initializing VNC server with TLS password auth\n");
3408 *subauth
= VNC_AUTH_VENCRYPT_TLSVNC
;
3413 VNC_DEBUG("Initializing VNC server with x509 SASL auth\n");
3414 *subauth
= VNC_AUTH_VENCRYPT_X509SASL
;
3416 VNC_DEBUG("Initializing VNC server with TLS SASL auth\n");
3417 *subauth
= VNC_AUTH_VENCRYPT_TLSSASL
;
3421 VNC_DEBUG("Initializing VNC server with x509 no auth\n");
3422 *subauth
= VNC_AUTH_VENCRYPT_X509NONE
;
3424 VNC_DEBUG("Initializing VNC server with TLS no auth\n");
3425 *subauth
= VNC_AUTH_VENCRYPT_TLSNONE
;
3434 * Handle back compat with old CLI syntax by creating some
3435 * suitable QCryptoTLSCreds objects
3437 static QCryptoTLSCreds
*
3438 vnc_display_create_creds(bool x509
,
3444 gchar
*credsid
= g_strdup_printf("tlsvnc%s", id
);
3445 Object
*parent
= object_get_objects_root();
3450 creds
= object_new_with_props(TYPE_QCRYPTO_TLS_CREDS_X509
,
3454 "endpoint", "server",
3456 "verify-peer", x509verify
? "yes" : "no",
3459 creds
= object_new_with_props(TYPE_QCRYPTO_TLS_CREDS_ANON
,
3463 "endpoint", "server",
3470 error_propagate(errp
, err
);
3474 return QCRYPTO_TLS_CREDS(creds
);
3478 void vnc_display_open(const char *id
, Error
**errp
)
3480 VncDisplay
*vd
= vnc_display_find(id
);
3481 QemuOpts
*opts
= qemu_opts_find(&qemu_vnc_opts
, id
);
3482 SocketAddress
*saddr
= NULL
, *wsaddr
= NULL
;
3483 const char *share
, *device_id
;
3485 bool password
= false;
3486 bool reverse
= false;
3490 int show_vnc_port
= 0;
3492 #ifdef CONFIG_VNC_SASL
3496 int lock_key_sync
= 1;
3498 bool ws_enabled
= false;
3501 error_setg(errp
, "VNC display not active");
3504 vnc_display_close(vd
);
3509 vnc
= qemu_opt_get(opts
, "vnc");
3510 if (!vnc
|| strcmp(vnc
, "none") == 0) {
3514 h
= strrchr(vnc
, ':');
3516 size_t hlen
= h
- vnc
;
3518 const char *websocket
= qemu_opt_get(opts
, "websocket");
3519 int to
= qemu_opt_get_number(opts
, "to", 0);
3520 bool has_ipv4
= qemu_opt_get(opts
, "ipv4");
3521 bool has_ipv6
= qemu_opt_get(opts
, "ipv6");
3522 bool ipv4
= qemu_opt_get_bool(opts
, "ipv4", false);
3523 bool ipv6
= qemu_opt_get_bool(opts
, "ipv6", false);
3525 saddr
= g_new0(SocketAddress
, 1);
3527 if (!qcrypto_hash_supports(QCRYPTO_HASH_ALG_SHA1
)) {
3529 "SHA1 hash support is required for websockets");
3533 wsaddr
= g_new0(SocketAddress
, 1);
3537 if (strncmp(vnc
, "unix:", 5) == 0) {
3538 saddr
->type
= SOCKET_ADDRESS_KIND_UNIX
;
3539 saddr
->u
.q_unix
.data
= g_new0(UnixSocketAddress
, 1);
3540 saddr
->u
.q_unix
.data
->path
= g_strdup(vnc
+ 5);
3543 error_setg(errp
, "UNIX sockets not supported with websock");
3547 unsigned long long baseport
;
3548 InetSocketAddress
*inet
;
3549 saddr
->type
= SOCKET_ADDRESS_KIND_INET
;
3550 inet
= saddr
->u
.inet
.data
= g_new0(InetSocketAddress
, 1);
3551 if (vnc
[0] == '[' && vnc
[hlen
- 1] == ']') {
3552 inet
->host
= g_strndup(vnc
+ 1, hlen
- 2);
3554 inet
->host
= g_strndup(vnc
, hlen
);
3556 if (parse_uint_full(h
+ 1, &baseport
, 10) < 0) {
3557 error_setg(errp
, "can't convert to a number: %s", h
+ 1);
3560 if (baseport
> 65535 ||
3561 baseport
+ 5900 > 65535) {
3562 error_setg(errp
, "port %s out of range", h
+ 1);
3565 inet
->port
= g_strdup_printf(
3566 "%d", (int)baseport
+ 5900);
3569 inet
->has_to
= true;
3570 inet
->to
= to
+ 5900;
3574 inet
->has_ipv4
= has_ipv4
;
3576 inet
->has_ipv6
= has_ipv6
;
3579 wsaddr
->type
= SOCKET_ADDRESS_KIND_INET
;
3580 inet
= wsaddr
->u
.inet
.data
= g_new0(InetSocketAddress
, 1);
3581 inet
->host
= g_strdup(saddr
->u
.inet
.data
->host
);
3582 inet
->port
= g_strdup(websocket
);
3585 inet
->has_to
= true;
3589 inet
->has_ipv4
= has_ipv4
;
3591 inet
->has_ipv6
= has_ipv6
;
3595 error_setg(errp
, "no vnc port specified");
3599 password
= qemu_opt_get_bool(opts
, "password", false);
3601 if (fips_get_state()) {
3603 "VNC password auth disabled due to FIPS mode, "
3604 "consider using the VeNCrypt or SASL authentication "
3605 "methods as an alternative");
3608 if (!qcrypto_cipher_supports(
3609 QCRYPTO_CIPHER_ALG_DES_RFB
)) {
3611 "Cipher backend does not support DES RFB algorithm");
3616 reverse
= qemu_opt_get_bool(opts
, "reverse", false);
3617 lock_key_sync
= qemu_opt_get_bool(opts
, "lock-key-sync", true);
3618 key_delay_ms
= qemu_opt_get_number(opts
, "key-delay-ms", 1);
3619 sasl
= qemu_opt_get_bool(opts
, "sasl", false);
3620 #ifndef CONFIG_VNC_SASL
3622 error_setg(errp
, "VNC SASL auth requires cyrus-sasl support");
3625 #endif /* CONFIG_VNC_SASL */
3626 credid
= qemu_opt_get(opts
, "tls-creds");
3629 if (qemu_opt_get(opts
, "tls") ||
3630 qemu_opt_get(opts
, "x509") ||
3631 qemu_opt_get(opts
, "x509verify")) {
3633 "'tls-creds' parameter is mutually exclusive with "
3634 "'tls', 'x509' and 'x509verify' parameters");
3638 creds
= object_resolve_path_component(
3639 object_get_objects_root(), credid
);
3641 error_setg(errp
, "No TLS credentials with id '%s'",
3645 vd
->tlscreds
= (QCryptoTLSCreds
*)
3646 object_dynamic_cast(creds
,
3647 TYPE_QCRYPTO_TLS_CREDS
);
3648 if (!vd
->tlscreds
) {
3649 error_setg(errp
, "Object with id '%s' is not TLS credentials",
3653 object_ref(OBJECT(vd
->tlscreds
));
3655 if (vd
->tlscreds
->endpoint
!= QCRYPTO_TLS_CREDS_ENDPOINT_SERVER
) {
3657 "Expecting TLS credentials with a server endpoint");
3662 bool tls
= false, x509
= false, x509verify
= false;
3663 tls
= qemu_opt_get_bool(opts
, "tls", false);
3665 path
= qemu_opt_get(opts
, "x509");
3670 path
= qemu_opt_get(opts
, "x509verify");
3676 vd
->tlscreds
= vnc_display_create_creds(x509
,
3681 if (!vd
->tlscreds
) {
3686 acl
= qemu_opt_get_bool(opts
, "acl", false);
3688 share
= qemu_opt_get(opts
, "share");
3690 if (strcmp(share
, "ignore") == 0) {
3691 vd
->share_policy
= VNC_SHARE_POLICY_IGNORE
;
3692 } else if (strcmp(share
, "allow-exclusive") == 0) {
3693 vd
->share_policy
= VNC_SHARE_POLICY_ALLOW_EXCLUSIVE
;
3694 } else if (strcmp(share
, "force-shared") == 0) {
3695 vd
->share_policy
= VNC_SHARE_POLICY_FORCE_SHARED
;
3697 error_setg(errp
, "unknown vnc share= option");
3701 vd
->share_policy
= VNC_SHARE_POLICY_ALLOW_EXCLUSIVE
;
3703 vd
->connections_limit
= qemu_opt_get_number(opts
, "connections", 32);
3705 #ifdef CONFIG_VNC_JPEG
3706 vd
->lossy
= qemu_opt_get_bool(opts
, "lossy", false);
3708 vd
->non_adaptive
= qemu_opt_get_bool(opts
, "non-adaptive", false);
3709 /* adaptive updates are only used with tight encoding and
3710 * if lossy updates are enabled so we can disable all the
3711 * calculations otherwise */
3713 vd
->non_adaptive
= true;
3717 if (strcmp(vd
->id
, "default") == 0) {
3718 vd
->tlsaclname
= g_strdup("vnc.x509dname");
3720 vd
->tlsaclname
= g_strdup_printf("vnc.%s.x509dname", vd
->id
);
3722 qemu_acl_init(vd
->tlsaclname
);
3724 #ifdef CONFIG_VNC_SASL
3728 if (strcmp(vd
->id
, "default") == 0) {
3729 aclname
= g_strdup("vnc.username");
3731 aclname
= g_strdup_printf("vnc.%s.username", vd
->id
);
3733 vd
->sasl
.acl
= qemu_acl_init(aclname
);
3738 if (vnc_display_setup_auth(&vd
->auth
, &vd
->subauth
,
3739 vd
->tlscreds
, password
,
3740 sasl
, false, errp
) < 0) {
3744 if (vnc_display_setup_auth(&vd
->ws_auth
, &vd
->ws_subauth
,
3745 vd
->tlscreds
, password
,
3746 sasl
, true, errp
) < 0) {
3750 #ifdef CONFIG_VNC_SASL
3751 if ((saslErr
= sasl_server_init(NULL
, "qemu")) != SASL_OK
) {
3752 error_setg(errp
, "Failed to initialize SASL auth: %s",
3753 sasl_errstring(saslErr
, NULL
, NULL
));
3757 vd
->lock_key_sync
= lock_key_sync
;
3758 vd
->key_delay_ms
= key_delay_ms
;
3760 device_id
= qemu_opt_get(opts
, "display");
3762 int head
= qemu_opt_get_number(opts
, "head", 0);
3765 con
= qemu_console_lookup_by_device_name(device_id
, head
, &err
);
3767 error_propagate(errp
, err
);
3774 if (con
!= vd
->dcl
.con
) {
3775 unregister_displaychangelistener(&vd
->dcl
);
3777 register_displaychangelistener(&vd
->dcl
);
3781 /* connect to viewer */
3782 QIOChannelSocket
*sioc
= NULL
;
3784 vd
->lwebsock
= NULL
;
3786 error_setg(errp
, "Cannot use websockets in reverse mode");
3789 vd
->is_unix
= saddr
->type
== SOCKET_ADDRESS_KIND_UNIX
;
3790 sioc
= qio_channel_socket_new();
3791 if (qio_channel_socket_connect_sync(sioc
, saddr
, errp
) < 0) {
3794 vnc_connect(vd
, sioc
, false, false);
3795 object_unref(OBJECT(sioc
));
3797 vd
->lsock
= qio_channel_socket_new();
3798 if (qio_channel_socket_listen_sync(vd
->lsock
, saddr
, errp
) < 0) {
3801 vd
->is_unix
= saddr
->type
== SOCKET_ADDRESS_KIND_UNIX
;
3804 vd
->lwebsock
= qio_channel_socket_new();
3805 if (qio_channel_socket_listen_sync(vd
->lwebsock
,
3806 wsaddr
, errp
) < 0) {
3807 object_unref(OBJECT(vd
->lsock
));
3813 vd
->lsock_tag
= qio_channel_add_watch(
3814 QIO_CHANNEL(vd
->lsock
),
3815 G_IO_IN
, vnc_listen_io
, vd
, NULL
);
3817 vd
->lwebsock_tag
= qio_channel_add_watch(
3818 QIO_CHANNEL(vd
->lwebsock
),
3819 G_IO_IN
, vnc_listen_io
, vd
, NULL
);
3823 if (show_vnc_port
) {
3824 vnc_display_print_local_addr(vd
);
3827 qapi_free_SocketAddress(saddr
);
3828 qapi_free_SocketAddress(wsaddr
);
3832 qapi_free_SocketAddress(saddr
);
3833 qapi_free_SocketAddress(wsaddr
);
3837 void vnc_display_add_client(const char *id
, int csock
, bool skipauth
)
3839 VncDisplay
*vd
= vnc_display_find(id
);
3840 QIOChannelSocket
*sioc
;
3846 sioc
= qio_channel_socket_new_fd(csock
, NULL
);
3848 vnc_connect(vd
, sioc
, skipauth
, false);
3849 object_unref(OBJECT(sioc
));
3853 static void vnc_auto_assign_id(QemuOptsList
*olist
, QemuOpts
*opts
)
3858 id
= g_strdup("default");
3859 while (qemu_opts_find(olist
, id
)) {
3861 id
= g_strdup_printf("vnc%d", i
++);
3863 qemu_opts_set_id(opts
, id
);
3866 QemuOpts
*vnc_parse(const char *str
, Error
**errp
)
3868 QemuOptsList
*olist
= qemu_find_opts("vnc");
3869 QemuOpts
*opts
= qemu_opts_parse(olist
, str
, true, errp
);
3876 id
= qemu_opts_id(opts
);
3878 /* auto-assign id if not present */
3879 vnc_auto_assign_id(olist
, opts
);
3884 int vnc_init_func(void *opaque
, QemuOpts
*opts
, Error
**errp
)
3886 Error
*local_err
= NULL
;
3887 char *id
= (char *)qemu_opts_id(opts
);
3890 vnc_display_init(id
);
3891 vnc_display_open(id
, &local_err
);
3892 if (local_err
!= NULL
) {
3893 error_reportf_err(local_err
, "Failed to start VNC server: ");
3899 static void vnc_register_config(void)
3901 qemu_add_opts(&qemu_vnc_opts
);
3903 opts_init(vnc_register_config
);