Lines Matching +full:- +full:- +full:refresh +full:- +full:keys
29 #include "vnc-jobs.h"
31 #include "hw/qdev-core.h"
34 #include "qemu/error-report.h"
35 #include "qemu/main-loop.h"
41 #include "qemu/config-file.h"
42 #include "qapi/qapi-emit-events.h"
43 #include "qapi/qapi-events-ui.h"
45 #include "qapi/qapi-commands-ui.h"
56 #include "io/dns-resolver.h"
84 fprintf(stderr, "%s/%p: %s -> %s\n", __func__, in vnc_set_share_mode()
85 vs->ioc, mn[vs->share_mode], mn[mode]); in vnc_set_share_mode()
88 switch (vs->share_mode) { in vnc_set_share_mode()
90 vs->vd->num_connecting--; in vnc_set_share_mode()
93 vs->vd->num_shared--; in vnc_set_share_mode()
96 vs->vd->num_exclusive--; in vnc_set_share_mode()
102 vs->share_mode = mode; in vnc_set_share_mode()
104 switch (vs->share_mode) { in vnc_set_share_mode()
106 vs->vd->num_connecting++; in vnc_set_share_mode()
109 vs->vd->num_shared++; in vnc_set_share_mode()
112 vs->vd->num_exclusive++; in vnc_set_share_mode()
124 switch (addr->type) { in vnc_init_basic_info()
126 info->host = g_strdup(addr->u.inet.host); in vnc_init_basic_info()
127 info->service = g_strdup(addr->u.inet.port); in vnc_init_basic_info()
128 if (addr->u.inet.ipv6) { in vnc_init_basic_info()
129 info->family = NETWORK_ADDRESS_FAMILY_IPV6; in vnc_init_basic_info()
131 info->family = NETWORK_ADDRESS_FAMILY_IPV4; in vnc_init_basic_info()
136 info->host = g_strdup(""); in vnc_init_basic_info()
137 info->service = g_strdup(addr->u.q_unix.path); in vnc_init_basic_info()
138 info->family = NETWORK_ADDRESS_FAMILY_UNIX; in vnc_init_basic_info()
144 SocketAddressType_str(addr->type)); in vnc_init_basic_info()
187 switch (vd->auth) { in vnc_auth_name()
205 switch (vd->subauth) { in vnc_auth_name()
238 if (!vd->listener || !vd->listener->nsioc) { in vnc_server_info_get()
243 vnc_init_basic_info_from_server_addr(vd->listener->sioc[0], in vnc_server_info_get()
245 info->auth = g_strdup(vnc_auth_name(vd)); in vnc_server_info_get()
256 if (!client->info) { in vnc_client_cache_auth()
260 if (client->tls) { in vnc_client_cache_auth()
261 client->info->x509_dname = in vnc_client_cache_auth()
262 qcrypto_tls_session_get_peer_name(client->tls); in vnc_client_cache_auth()
265 if (client->sasl.conn && in vnc_client_cache_auth()
266 client->sasl.username) { in vnc_client_cache_auth()
267 client->info->sasl_username = g_strdup(client->sasl.username); in vnc_client_cache_auth()
276 client->info = g_malloc0(sizeof(*client->info)); in vnc_client_cache_addr()
277 vnc_init_basic_info_from_remote_addr(client->sioc, in vnc_client_cache_addr()
278 qapi_VncClientInfo_base(client->info), in vnc_client_cache_addr()
280 client->info->websocket = client->websocket; in vnc_client_cache_addr()
282 qapi_free_VncClientInfo(client->info); in vnc_client_cache_addr()
283 client->info = NULL; in vnc_client_cache_addr()
292 if (!vs->info) { in vnc_qmp_event()
296 si = vnc_server_info_get(vs->vd); in vnc_qmp_event()
303 qapi_event_send_vnc_connected(si, qapi_VncClientInfo_base(vs->info)); in vnc_qmp_event()
306 qapi_event_send_vnc_initialized(si, vs->info); in vnc_qmp_event()
309 qapi_event_send_vnc_disconnected(si, vs->info); in vnc_qmp_event()
325 vnc_init_basic_info_from_remote_addr(client->sioc, in qmp_query_vnc_client()
334 info->websocket = client->websocket; in qmp_query_vnc_client()
336 if (client->tls) { in qmp_query_vnc_client()
337 info->x509_dname = qcrypto_tls_session_get_peer_name(client->tls); in qmp_query_vnc_client()
340 if (client->sasl.conn && client->sasl.username) { in qmp_query_vnc_client()
341 info->sasl_username = g_strdup(client->sasl.username); in qmp_query_vnc_client()
356 if (strcmp(id, vd->id) == 0) { in vnc_display_find()
368 QTAILQ_FOREACH(client, &vd->clients, next) { in qmp_query_client_list()
380 if (vd == NULL || !vd->listener || !vd->listener->nsioc) { in qmp_query_vnc()
381 info->enabled = false; in qmp_query_vnc()
383 info->enabled = true; in qmp_query_vnc()
386 info->has_clients = true; in qmp_query_vnc()
387 info->clients = qmp_query_client_list(vd); in qmp_query_vnc()
389 addr = qio_channel_socket_get_local_address(vd->listener->sioc[0], in qmp_query_vnc()
395 switch (addr->type) { in qmp_query_vnc()
397 info->host = g_strdup(addr->u.inet.host); in qmp_query_vnc()
398 info->service = g_strdup(addr->u.inet.port); in qmp_query_vnc()
399 if (addr->u.inet.ipv6) { in qmp_query_vnc()
400 info->family = NETWORK_ADDRESS_FAMILY_IPV6; in qmp_query_vnc()
402 info->family = NETWORK_ADDRESS_FAMILY_IPV4; in qmp_query_vnc()
407 info->host = g_strdup(""); in qmp_query_vnc()
408 info->service = g_strdup(addr->u.q_unix.path); in qmp_query_vnc()
409 info->family = NETWORK_ADDRESS_FAMILY_UNIX; in qmp_query_vnc()
415 SocketAddressType_str(addr->type)); in qmp_query_vnc()
421 info->has_family = true; in qmp_query_vnc()
423 info->auth = g_strdup(vnc_auth_name(vd)); in qmp_query_vnc()
464 info->websocket = websocket; in qmp_query_server_entry()
466 qmp_query_auth(auth, subauth, &info->auth, in qmp_query_server_entry()
467 &info->vencrypt, &info->has_vencrypt); in qmp_query_server_entry()
553 info->id = g_strdup(vd->id); in qmp_query_vnc_servers()
554 info->clients = qmp_query_client_list(vd); in qmp_query_vnc_servers()
555 qmp_query_auth(vd->auth, vd->subauth, &info->auth, in qmp_query_vnc_servers()
556 &info->vencrypt, &info->has_vencrypt); in qmp_query_vnc_servers()
557 if (vd->dcl.con) { in qmp_query_vnc_servers()
558 dev = DEVICE(object_property_get_link(OBJECT(vd->dcl.con), in qmp_query_vnc_servers()
560 info->display = g_strdup(dev->id); in qmp_query_vnc_servers()
562 for (i = 0; vd->listener != NULL && i < vd->listener->nsioc; i++) { in qmp_query_vnc_servers()
563 info->server = qmp_query_server_entry( in qmp_query_vnc_servers()
564 vd->listener->sioc[i], false, vd->auth, vd->subauth, in qmp_query_vnc_servers()
565 info->server); in qmp_query_vnc_servers()
567 for (i = 0; vd->wslistener != NULL && i < vd->wslistener->nsioc; i++) { in qmp_query_vnc_servers()
568 info->server = qmp_query_server_entry( in qmp_query_vnc_servers()
569 vd->wslistener->sioc[i], true, vd->ws_auth, in qmp_query_vnc_servers()
570 vd->ws_subauth, info->server); in qmp_query_vnc_servers()
588 if (!vd->tlscreds) { in vnc_display_reload_certs()
593 creds = QCRYPTO_TLS_CREDS_GET_CLASS(OBJECT(vd->tlscreds)); in vnc_display_reload_certs()
594 if (creds->reload == NULL) { in vnc_display_reload_certs()
596 object_get_typename(OBJECT(vd->tlscreds))); in vnc_display_reload_certs()
599 if (!creds->reload(vd->tlscreds, errp)) { in vnc_display_reload_certs()
608 2) there is some weirdness when using the -S option (the screen is grey
625 return MIN(VNC_MAX_WIDTH, ROUND_UP(surface_width(vd->ds), in vnc_width()
631 return MIN(VNC_MAX_WIDTH, surface_width(vd->ds)); in vnc_true_width()
636 return MIN(VNC_MAX_HEIGHT, surface_height(vd->ds)); in vnc_height()
650 x -= (x % VNC_DIRTY_PIXELS_PER_BIT);
654 w = MIN(x + w, width) - x;
667 struct VncSurface *s = &vd->guest; in vnc_dpy_update()
669 vnc_set_area_dirty(s->dirty, vd, x, y, w, h); in vnc_dpy_update()
686 vs, vs->ioc, vs->client_width, vs->client_height, reject_reason); in vnc_desktop_resize_ext()
695 vs->client_width, vs->client_height, in vnc_desktop_resize_ext()
702 vnc_write_u16(vs, 0); /* screen x-pos */ in vnc_desktop_resize_ext()
703 vnc_write_u16(vs, 0); /* screen y-pos */ in vnc_desktop_resize_ext()
704 vnc_write_u16(vs, vs->client_width); in vnc_desktop_resize_ext()
705 vnc_write_u16(vs, vs->client_height); in vnc_desktop_resize_ext()
713 if (vs->ioc == NULL || (!vnc_has_feature(vs, VNC_FEATURE_RESIZE) && in vnc_desktop_resize()
717 if (vs->client_width == vs->vd->true_width && in vnc_desktop_resize()
718 vs->client_height == pixman_image_get_height(vs->vd->server)) { in vnc_desktop_resize()
722 assert(vs->vd->true_width < 65536 && in vnc_desktop_resize()
723 vs->vd->true_width >= 0); in vnc_desktop_resize()
724 assert(pixman_image_get_height(vs->vd->server) < 65536 && in vnc_desktop_resize()
725 pixman_image_get_height(vs->vd->server) >= 0); in vnc_desktop_resize()
726 vs->client_width = vs->vd->true_width; in vnc_desktop_resize()
727 vs->client_height = pixman_image_get_height(vs->vd->server); in vnc_desktop_resize()
735 vs, vs->ioc, vs->client_width, vs->client_height); in vnc_desktop_resize()
741 vnc_framebuffer_update(vs, 0, 0, vs->client_width, vs->client_height, in vnc_desktop_resize()
751 QTAILQ_FOREACH(vs, &vd->clients, next) { in vnc_abort_display_jobs()
753 vs->abort = true; in vnc_abort_display_jobs()
756 QTAILQ_FOREACH(vs, &vd->clients, next) { in vnc_abort_display_jobs()
759 QTAILQ_FOREACH(vs, &vd->clients, next) { in vnc_abort_display_jobs()
761 if (vs->update == VNC_STATE_UPDATE_NONE && in vnc_abort_display_jobs()
762 vs->job_update != VNC_STATE_UPDATE_NONE) { in vnc_abort_display_jobs()
764 vs->update = vs->job_update; in vnc_abort_display_jobs()
765 vs->job_update = VNC_STATE_UPDATE_NONE; in vnc_abort_display_jobs()
767 vs->abort = false; in vnc_abort_display_jobs()
774 return pixman_image_get_stride(vd->server); in vnc_server_fb_stride()
781 ptr = (uint8_t *)pixman_image_get_data(vd->server); in vnc_server_fb_ptr()
791 qemu_pixman_image_unref(vd->server); in vnc_update_server_surface()
792 vd->server = NULL; in vnc_update_server_surface()
794 if (QTAILQ_EMPTY(&vd->clients)) { in vnc_update_server_surface()
800 vd->true_width = vnc_true_width(vd); in vnc_update_server_surface()
801 vd->server = pixman_image_create_bits(VNC_SERVER_FB_FORMAT, in vnc_update_server_surface()
805 memset(vd->guest.dirty, 0x00, sizeof(vd->guest.dirty)); in vnc_update_server_surface()
806 vnc_set_area_dirty(vd->guest.dirty, vd, 0, 0, in vnc_update_server_surface()
825 bool pageflip = vnc_check_pageflip(vd->ds, surface); in vnc_dpy_switch()
829 vd->ds = surface; in vnc_dpy_switch()
832 qemu_pixman_image_unref(vd->guest.fb); in vnc_dpy_switch()
833 vd->guest.fb = pixman_image_ref(surface->image); in vnc_dpy_switch()
834 vd->guest.format = surface_format(surface); in vnc_dpy_switch()
842 vnc_set_area_dirty(vd->guest.dirty, vd, 0, 0, in vnc_dpy_switch()
855 QTAILQ_FOREACH(vs, &vd->clients, next) { in vnc_dpy_switch()
859 memset(vs->dirty, 0x00, sizeof(vs->dirty)); in vnc_dpy_switch()
860 vnc_set_area_dirty(vs->dirty, vd, 0, 0, in vnc_dpy_switch()
880 r = (((v & 0x00ff0000) >> 16) << vs->client_pf.rbits) >> 8; in vnc_convert_pixel()
881 g = (((v & 0x0000ff00) >> 8) << vs->client_pf.gbits) >> 8; in vnc_convert_pixel()
882 b = (((v & 0x000000ff) >> 0) << vs->client_pf.bbits) >> 8; in vnc_convert_pixel()
886 v = (r << vs->client_pf.rshift) | in vnc_convert_pixel()
887 (g << vs->client_pf.gshift) | in vnc_convert_pixel()
888 (b << vs->client_pf.bshift); in vnc_convert_pixel()
889 switch (vs->client_pf.bytes_per_pixel) { in vnc_convert_pixel()
894 if (vs->client_endian == G_BIG_ENDIAN) { in vnc_convert_pixel()
904 if (vs->client_endian == G_BIG_ENDIAN) { in vnc_convert_pixel()
930 vnc_write(vs, buf, vs->client_pf.bytes_per_pixel); in vnc_write_pixels_generic()
939 VncDisplay *vd = vs->vd; in vnc_raw_send_framebuffer_update()
943 vs->write_pixels(vs, row, w * VNC_SERVER_FB_BYTES); in vnc_raw_send_framebuffer_update()
953 switch(vs->vnc_encoding) { in vnc_send_framebuffer_update()
989 QEMUCursor *c = qemu_console_get_cursor(vs->vd->dcl.con); in vnc_cursor_define()
993 return -1; in vnc_cursor_define()
1001 vnc_framebuffer_update(vs, c->hot_x, c->hot_y, c->width, c->height, in vnc_cursor_define()
1004 vnc_write(vs, c->data, c->width * c->height * 4); in vnc_cursor_define()
1013 vnc_framebuffer_update(vs, c->hot_x, c->hot_y, c->width, c->height, in vnc_cursor_define()
1015 isize = c->width * c->height * vs->client_pf.bytes_per_pixel; in vnc_cursor_define()
1016 vnc_write_pixels_generic(vs, c->data, isize); in vnc_cursor_define()
1017 vnc_write(vs, vs->vd->cursor_mask, vs->vd->cursor_msize); in vnc_cursor_define()
1021 return -1; in vnc_cursor_define()
1030 g_free(vd->cursor_mask); in vnc_dpy_cursor_define()
1031 vd->cursor_msize = cursor_get_mono_bpl(c) * c->height; in vnc_dpy_cursor_define()
1032 vd->cursor_mask = g_malloc0(vd->cursor_msize); in vnc_dpy_cursor_define()
1033 cursor_get_mono_mask(c, 0, vd->cursor_mask); in vnc_dpy_cursor_define()
1035 QTAILQ_FOREACH(vs, &vd->clients, next) { in vnc_dpy_cursor_define()
1045 for (h = 1; h < (height - y); h++) { in find_and_clear_dirty_height()
1046 if (!test_bit(last_x, vs->dirty[y + h])) { in find_and_clear_dirty_height()
1049 bitmap_clear(vs->dirty[y + h], last_x, x - last_x); in find_and_clear_dirty_height()
1068 vs->client_width * vs->client_height * vs->client_pf.bytes_per_pixel; in vnc_update_throttle_offset()
1070 if (vs->audio_cap) { in vnc_update_throttle_offset()
1072 switch (vs->as.fmt) { in vnc_update_throttle_offset()
1087 offset += vs->as.freq * bps * vs->as.nchannels; in vnc_update_throttle_offset()
1096 if (vs->throttle_output_offset != offset) { in vnc_update_throttle_offset()
1098 vs, vs->ioc, vs->throttle_output_offset, offset, vs->client_width, in vnc_update_throttle_offset()
1099 vs->client_height, vs->client_pf.bytes_per_pixel, vs->audio_cap); in vnc_update_throttle_offset()
1102 vs->throttle_output_offset = offset; in vnc_update_throttle_offset()
1107 switch (vs->update) { in vnc_should_update()
1115 if (vs->output.offset < vs->throttle_output_offset && in vnc_should_update()
1116 vs->job_update == VNC_STATE_UPDATE_NONE) { in vnc_should_update()
1120 vs, vs->ioc, vs->job_update, vs->output.offset); in vnc_should_update()
1131 if (vs->force_update_offset == 0 && in vnc_should_update()
1132 vs->job_update == VNC_STATE_UPDATE_NONE) { in vnc_should_update()
1136 vs, vs->ioc, vs->job_update, vs->force_update_offset); in vnc_should_update()
1144 VncDisplay *vd = vs->vd; in vnc_update_client()
1150 if (vs->disconnecting) { in vnc_update_client()
1155 vs->has_dirty += has_dirty; in vnc_update_client()
1160 if (!vs->has_dirty && vs->update != VNC_STATE_UPDATE_FORCE) { in vnc_update_client()
1172 height = pixman_image_get_height(vd->server); in vnc_update_client()
1173 width = pixman_image_get_width(vd->server); in vnc_update_client()
1179 unsigned long offset = find_next_bit((unsigned long *) &vs->dirty, in vnc_update_client()
1188 x2 = find_next_zero_bit((unsigned long *) &vs->dirty[y], in vnc_update_client()
1190 bitmap_clear(vs->dirty[y], x, x2 - x); in vnc_update_client()
1195 (x2 - x) * VNC_DIRTY_PIXELS_PER_BIT, h); in vnc_update_client()
1205 vs->job_update = vs->update; in vnc_update_client()
1206 vs->update = VNC_STATE_UPDATE_NONE; in vnc_update_client()
1208 vs->has_dirty = 0; in vnc_update_client()
1217 assert(vs->magic == VNC_MAGIC); in audio_capture_notify()
1220 trace_vnc_msg_server_audio_end(vs, vs->ioc); in audio_capture_notify()
1230 trace_vnc_msg_server_audio_begin(vs, vs->ioc); in audio_capture_notify()
1249 assert(vs->magic == VNC_MAGIC); in audio_capture()
1250 trace_vnc_msg_server_audio_data(vs, vs->ioc, buf, size); in audio_capture()
1252 if (vs->output.offset < vs->throttle_output_offset) { in audio_capture()
1259 trace_vnc_client_throttle_audio(vs, vs->ioc, vs->output.offset); in audio_capture()
1269 if (vs->audio_cap) { in audio_add()
1278 vs->audio_cap = AUD_add_capture(vs->vd->audio_state, &vs->as, &ops, vs); in audio_add()
1279 if (!vs->audio_cap) { in audio_add()
1286 if (vs->audio_cap) { in audio_del()
1287 AUD_del_capture(vs->audio_cap, vs); in audio_del()
1288 vs->audio_cap = NULL; in audio_del()
1294 if (vs->disconnecting) { in vnc_disconnect_start()
1297 trace_vnc_client_disconnect_start(vs, vs->ioc); in vnc_disconnect_start()
1299 if (vs->ioc_tag) { in vnc_disconnect_start()
1300 g_source_remove(vs->ioc_tag); in vnc_disconnect_start()
1301 vs->ioc_tag = 0; in vnc_disconnect_start()
1303 qio_channel_close(vs->ioc, NULL); in vnc_disconnect_start()
1304 vs->disconnecting = TRUE; in vnc_disconnect_start()
1311 trace_vnc_client_disconnect_finish(vs, vs->ioc); in vnc_disconnect_finish()
1318 buffer_free(&vs->input); in vnc_disconnect_finish()
1319 buffer_free(&vs->output); in vnc_disconnect_finish()
1321 qapi_free_VncClientInfo(vs->info); in vnc_disconnect_finish()
1331 qkbd_state_lift_all_keys(vs->vd->kbd); in vnc_disconnect_finish()
1333 if (vs->mouse_mode_notifier.notify != NULL) { in vnc_disconnect_finish()
1334 qemu_remove_mouse_mode_change_notifier(&vs->mouse_mode_notifier); in vnc_disconnect_finish()
1336 QTAILQ_REMOVE(&vs->vd->clients, vs, next); in vnc_disconnect_finish()
1337 if (QTAILQ_EMPTY(&vs->vd->clients)) { in vnc_disconnect_finish()
1339 vnc_update_server_surface(vs->vd); in vnc_disconnect_finish()
1343 if (vs->cbpeer.notifier.notify) { in vnc_disconnect_finish()
1344 qemu_clipboard_peer_unregister(&vs->cbpeer); in vnc_disconnect_finish()
1347 qemu_mutex_destroy(&vs->output_mutex); in vnc_disconnect_finish()
1348 if (vs->bh != NULL) { in vnc_disconnect_finish()
1349 qemu_bh_delete(vs->bh); in vnc_disconnect_finish()
1351 buffer_free(&vs->jobs_buffer); in vnc_disconnect_finish()
1354 g_free(vs->lossy_rect[i]); in vnc_disconnect_finish()
1356 g_free(vs->lossy_rect); in vnc_disconnect_finish()
1358 object_unref(OBJECT(vs->ioc)); in vnc_disconnect_finish()
1359 vs->ioc = NULL; in vnc_disconnect_finish()
1360 object_unref(OBJECT(vs->sioc)); in vnc_disconnect_finish()
1361 vs->sioc = NULL; in vnc_disconnect_finish()
1362 vs->magic = 0; in vnc_disconnect_finish()
1363 g_free(vs->zrle); in vnc_disconnect_finish()
1364 g_free(vs->tight); in vnc_disconnect_finish()
1372 trace_vnc_client_eof(vs, vs->ioc); in vnc_client_io_error()
1375 trace_vnc_client_io_error(vs, vs->ioc, in vnc_client_io_error()
1402 * though, since SASL encryption will typically be a no-op if TLS
1413 ret = qio_channel_write(vs->ioc, (const char *)data, datalen, &err); in vnc_client_write_buf()
1414 VNC_DEBUG("Wrote wire %p %zd -> %ld\n", data, datalen, ret); in vnc_client_write_buf()
1436 vs->output.buffer, vs->output.capacity, vs->output.offset, in vnc_client_write_plain()
1437 vs->sasl.waitWriteSSF); in vnc_client_write_plain()
1439 if (vs->sasl.conn && in vnc_client_write_plain()
1440 vs->sasl.runSSF && in vnc_client_write_plain()
1441 vs->sasl.waitWriteSSF) { in vnc_client_write_plain()
1442 ret = vnc_client_write_buf(vs, vs->output.buffer, vs->sasl.waitWriteSSF); in vnc_client_write_plain()
1444 vs->sasl.waitWriteSSF -= ret; in vnc_client_write_plain()
1447 ret = vnc_client_write_buf(vs, vs->output.buffer, vs->output.offset); in vnc_client_write_plain()
1451 if (ret >= vs->force_update_offset) { in vnc_client_write_plain()
1452 if (vs->force_update_offset != 0) { in vnc_client_write_plain()
1453 trace_vnc_client_unthrottle_forced(vs, vs->ioc); in vnc_client_write_plain()
1455 vs->force_update_offset = 0; in vnc_client_write_plain()
1457 vs->force_update_offset -= ret; in vnc_client_write_plain()
1459 offset = vs->output.offset; in vnc_client_write_plain()
1460 buffer_advance(&vs->output, ret); in vnc_client_write_plain()
1461 if (offset >= vs->throttle_output_offset && in vnc_client_write_plain()
1462 vs->output.offset < vs->throttle_output_offset) { in vnc_client_write_plain()
1463 trace_vnc_client_unthrottle_incremental(vs, vs->ioc, vs->output.offset); in vnc_client_write_plain()
1466 if (vs->output.offset == 0) { in vnc_client_write_plain()
1467 if (vs->ioc_tag) { in vnc_client_write_plain()
1468 g_source_remove(vs->ioc_tag); in vnc_client_write_plain()
1470 vs->ioc_tag = qio_channel_add_watch( in vnc_client_write_plain()
1471 vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR, in vnc_client_write_plain()
1487 if (vs->sasl.conn && in vnc_client_write_locked()
1488 vs->sasl.runSSF && in vnc_client_write_locked()
1489 !vs->sasl.waitWriteSSF) { in vnc_client_write_locked()
1500 assert(vs->magic == VNC_MAGIC); in vnc_client_write()
1502 if (vs->output.offset) { in vnc_client_write()
1504 } else if (vs->ioc != NULL) { in vnc_client_write()
1505 if (vs->ioc_tag) { in vnc_client_write()
1506 g_source_remove(vs->ioc_tag); in vnc_client_write()
1508 vs->ioc_tag = qio_channel_add_watch( in vnc_client_write()
1509 vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR, in vnc_client_write()
1517 vs->read_handler = func; in vnc_read_when()
1518 vs->read_handler_expect = expecting; in vnc_read_when()
1530 * though, since SASL encryption will typically be a no-op if TLS
1541 ret = qio_channel_read(vs->ioc, (char *)data, datalen, &err); in vnc_client_read_buf()
1542 VNC_DEBUG("Read wire %p %zd -> %ld\n", data, datalen, ret); in vnc_client_read_buf()
1560 vs->input.buffer, vs->input.capacity, vs->input.offset); in vnc_client_read_plain()
1561 buffer_reserve(&vs->input, 4096); in vnc_client_read_plain()
1562 ret = vnc_client_read_buf(vs, buffer_end(&vs->input), 4096); in vnc_client_read_plain()
1565 vs->input.offset += ret; in vnc_client_read_plain()
1573 assert(vs->magic == VNC_MAGIC); in vnc_jobs_bh()
1581 * Returns 0 on success, -1 if client disconnected
1588 if (vs->sasl.conn && vs->sasl.runSSF) in vnc_client_read()
1594 if (vs->disconnecting) { in vnc_client_read()
1596 return -1; in vnc_client_read()
1601 while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) { in vnc_client_read()
1602 size_t len = vs->read_handler_expect; in vnc_client_read()
1605 ret = vs->read_handler(vs, vs->input.buffer, len); in vnc_client_read()
1606 if (vs->disconnecting) { in vnc_client_read()
1608 return -1; in vnc_client_read()
1612 buffer_advance(&vs->input, len); in vnc_client_read()
1614 vs->read_handler_expect = ret; in vnc_client_read()
1625 assert(vs->magic == VNC_MAGIC); in vnc_client_io()
1642 if (vs->disconnecting) { in vnc_client_io()
1643 if (vs->ioc_tag != 0) { in vnc_client_io()
1644 g_source_remove(vs->ioc_tag); in vnc_client_io()
1646 vs->ioc_tag = 0; in vnc_client_io()
1653 * Scale factor to apply to vs->throttle_output_offset when checking for
1663 assert(vs->magic == VNC_MAGIC); in vnc_write()
1664 if (vs->disconnecting) { in vnc_write()
1672 * this higher level if a huge number of pseudo-encodings get in vnc_write()
1678 if (vs->throttle_output_offset != 0 && in vnc_write()
1679 (vs->output.offset / VNC_THROTTLE_OUTPUT_LIMIT_SCALE) > in vnc_write()
1680 vs->throttle_output_offset) { in vnc_write()
1681 trace_vnc_client_output_limit(vs, vs->ioc, vs->output.offset, in vnc_write()
1682 vs->throttle_output_offset); in vnc_write()
1686 buffer_reserve(&vs->output, len); in vnc_write()
1688 if (vs->ioc != NULL && buffer_empty(&vs->output)) { in vnc_write()
1689 if (vs->ioc_tag) { in vnc_write()
1690 g_source_remove(vs->ioc_tag); in vnc_write()
1692 vs->ioc_tag = qio_channel_add_watch( in vnc_write()
1693 vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_OUT, in vnc_write()
1697 buffer_append(&vs->output, data, len); in vnc_write()
1735 if (vs->ioc != NULL && vs->output.offset) { in vnc_flush()
1738 if (vs->disconnecting) { in vnc_flush()
1739 if (vs->ioc_tag != 0) { in vnc_flush()
1740 g_source_remove(vs->ioc_tag); in vnc_flush()
1742 vs->ioc_tag = 0; in vnc_flush()
1772 int absolute = qemu_input_is_absolute(vs->vd->dcl.con); in check_pointer_type_change()
1774 if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE) && vs->absolute != absolute) { in check_pointer_type_change()
1780 pixman_image_get_width(vs->vd->server), in check_pointer_type_change()
1781 pixman_image_get_height(vs->vd->server), in check_pointer_type_change()
1786 vs->absolute = absolute; in check_pointer_type_change()
1798 QemuConsole *con = vs->vd->dcl.con; in pointer_event()
1799 int width = pixman_image_get_width(vs->vd->server); in pointer_event()
1800 int height = pixman_image_get_height(vs->vd->server); in pointer_event()
1802 if (vs->last_bmask != button_mask) { in pointer_event()
1803 qemu_input_update_buttons(con, bmap, vs->last_bmask, button_mask); in pointer_event()
1804 vs->last_bmask = button_mask; in pointer_event()
1807 if (vs->absolute) { in pointer_event()
1811 qemu_input_queue_rel(con, INPUT_AXIS_X, x - 0x7FFF); in pointer_event()
1812 qemu_input_queue_rel(con, INPUT_AXIS_Y, y - 0x7FFF); in pointer_event()
1814 if (vs->last_x != -1) { in pointer_event()
1815 qemu_input_queue_rel(con, INPUT_AXIS_X, x - vs->last_x); in pointer_event()
1816 qemu_input_queue_rel(con, INPUT_AXIS_Y, y - vs->last_y); in pointer_event()
1818 vs->last_x = x; in pointer_event()
1819 vs->last_y = y; in pointer_event()
1826 qkbd_state_key_event(vs->vd->kbd, qcode, true); in press_key()
1827 qkbd_state_key_event(vs->vd->kbd, qcode, false); in press_key()
1841 vnc_write_u8(vs, vs->vd->ledstate); in vnc_led_state_change()
1855 if (ledstate == vd->ledstate) { in kbd_leds()
1859 vd->ledstate = ledstate; in kbd_leds()
1861 QTAILQ_FOREACH(client, &vd->clients, next) { in kbd_leds()
1872 case Q_KEY_CODE_1 ... Q_KEY_CODE_9: /* '1' to '9' keys */ in do_key_event()
1874 qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CTRL) && in do_key_event()
1875 qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_ALT)) { in do_key_event()
1876 QemuConsole *con = qemu_console_lookup_by_index(qcode - Q_KEY_CODE_1); in do_key_event()
1878 unregister_displaychangelistener(&vs->vd->dcl); in do_key_event()
1879 qkbd_state_switch_console(vs->vd->kbd, con); in do_key_event()
1880 vs->vd->dcl.con = con; in do_key_event()
1881 register_displaychangelistener(&vs->vd->dcl); in do_key_event()
1892 if (down && vs->vd->lock_key_sync && in do_key_event()
1894 keycode_is_keypad(vs->vd->kbd_layout, keycode)) { in do_key_event()
1899 if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) { in do_key_event()
1900 if (!qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUMLOCK)) { in do_key_event()
1905 if (qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUMLOCK)) { in do_key_event()
1912 if (down && vs->vd->lock_key_sync && in do_key_event()
1920 bool shift = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_SHIFT); in do_key_event()
1921 bool capslock = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CAPSLOCK); in do_key_event()
1935 qkbd_state_key_event(vs->vd->kbd, qcode, down); in do_key_event()
1936 if (QEMU_IS_TEXT_CONSOLE(vs->vd->dcl.con)) { in do_key_event()
1937 QemuTextConsole *con = QEMU_TEXT_CONSOLE(vs->vd->dcl.con); in do_key_event()
1938 bool numlock = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUMLOCK); in do_key_event()
1939 bool control = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CTRL); in do_key_event()
2019 qemu_text_console_put_keysym(con, '-'); in do_key_event()
2050 if (lsym >= 'A' && lsym <= 'Z' && qemu_console_is_graphic(vs->vd->dcl.con)) { in key_event()
2051 lsym = lsym - 'A' + 'a'; in key_event()
2054 keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF, in key_event()
2055 vs->vd->kbd, down) & SCANCODE_KEYMASK; in key_event()
2076 if (vs->update != VNC_STATE_UPDATE_FORCE) { in framebuffer_update_request()
2077 vs->update = VNC_STATE_UPDATE_INCREMENTAL; in framebuffer_update_request()
2080 vs->update = VNC_STATE_UPDATE_FORCE; in framebuffer_update_request()
2081 vnc_set_area_dirty(vs->dirty, vs->vd, x, y, w, h); in framebuffer_update_request()
2095 pixman_image_get_width(vs->vd->server), in send_ext_key_event_ack()
2096 pixman_image_get_height(vs->vd->server), in send_ext_key_event_ack()
2109 pixman_image_get_width(vs->vd->server), in send_ext_audio_ack()
2110 pixman_image_get_height(vs->vd->server), in send_ext_audio_ack()
2132 vs->features = 0; in set_encodings()
2133 vs->vnc_encoding = 0; in set_encodings()
2134 vs->tight->compression = 9; in set_encodings()
2135 vs->tight->quality = -1; /* Lossless by default */ in set_encodings()
2136 vs->absolute = -1; in set_encodings()
2143 for (i = n_encodings - 1; i >= 0; i--) { in set_encodings()
2147 vs->vnc_encoding = enc; in set_encodings()
2151 vs->vnc_encoding = enc; in set_encodings()
2155 vs->vnc_encoding = enc; in set_encodings()
2160 vs->vnc_encoding = enc; in set_encodings()
2171 vs->vnc_encoding = enc; in set_encodings()
2176 vs->vnc_encoding = enc; in set_encodings()
2180 vs->vnc_encoding = enc; in set_encodings()
2201 if (vs->vd->audio_state) { in set_encodings()
2213 if (vs->vd->power_control) { in set_encodings()
2223 vs->tight->compression = (enc & 0x0F); in set_encodings()
2226 if (vs->vd->lossy) { in set_encodings()
2227 vs->tight->quality = (enc & 0x0F); in set_encodings()
2236 check_pointer_type_change(&vs->mouse_mode_notifier, NULL); in set_encodings()
2243 pixman_format_code_t fmt = qemu_pixman_get_format(&vs->client_pf, in set_pixel_conversion()
2244 vs->client_endian); in set_pixel_conversion()
2247 vs->write_pixels = vnc_write_pixels_copy; in set_pixel_conversion()
2250 vs->write_pixels = vnc_write_pixels_generic; in set_pixel_conversion()
2266 PixelFormat *pf = &vs->client_pf; in send_color_map()
2268 vnc_write_u16(vs, (((i >> pf->rshift) & pf->rmax) << (16 - pf->rbits))); in send_color_map()
2269 vnc_write_u16(vs, (((i >> pf->gshift) & pf->gmax) << (16 - pf->gbits))); in send_color_map()
2270 vnc_write_u16(vs, (((i >> pf->bshift) & pf->bmax) << (16 - pf->bbits))); in send_color_map()
2301 vs->client_pf.rmax = red_max ? red_max : 0xFF; in set_pixel_format()
2302 vs->client_pf.rbits = ctpopl(red_max); in set_pixel_format()
2303 vs->client_pf.rshift = red_shift; in set_pixel_format()
2304 vs->client_pf.rmask = red_max << red_shift; in set_pixel_format()
2305 vs->client_pf.gmax = green_max ? green_max : 0xFF; in set_pixel_format()
2306 vs->client_pf.gbits = ctpopl(green_max); in set_pixel_format()
2307 vs->client_pf.gshift = green_shift; in set_pixel_format()
2308 vs->client_pf.gmask = green_max << green_shift; in set_pixel_format()
2309 vs->client_pf.bmax = blue_max ? blue_max : 0xFF; in set_pixel_format()
2310 vs->client_pf.bbits = ctpopl(blue_max); in set_pixel_format()
2311 vs->client_pf.bshift = blue_shift; in set_pixel_format()
2312 vs->client_pf.bmask = blue_max << blue_shift; in set_pixel_format()
2313 vs->client_pf.bits_per_pixel = bits_per_pixel; in set_pixel_format()
2314 vs->client_pf.bytes_per_pixel = bits_per_pixel / 8; in set_pixel_format()
2315 vs->client_pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel; in set_pixel_format()
2316 vs->client_endian = big_endian_flag ? G_BIG_ENDIAN : G_LITTLE_ENDIAN; in set_pixel_format()
2324 graphic_hw_invalidate(vs->vd->dcl.con); in set_pixel_format()
2325 graphic_hw_update(vs->vd->dcl.con); in set_pixel_format()
2331 vs->client_pf = qemu_default_pixelformat(32); in pixel_format_message()
2333 vnc_write_u8(vs, vs->client_pf.bits_per_pixel); /* bits-per-pixel */ in pixel_format_message()
2334 vnc_write_u8(vs, vs->client_pf.depth); /* depth */ in pixel_format_message()
2337 vnc_write_u8(vs, 1); /* big-endian-flag */ in pixel_format_message()
2339 vnc_write_u8(vs, 0); /* big-endian-flag */ in pixel_format_message()
2341 vnc_write_u8(vs, 1); /* true-color-flag */ in pixel_format_message()
2342 vnc_write_u16(vs, vs->client_pf.rmax); /* red-max */ in pixel_format_message()
2343 vnc_write_u16(vs, vs->client_pf.gmax); /* green-max */ in pixel_format_message()
2344 vnc_write_u16(vs, vs->client_pf.bmax); /* blue-max */ in pixel_format_message()
2345 vnc_write_u8(vs, vs->client_pf.rshift); /* red-shift */ in pixel_format_message()
2346 vnc_write_u8(vs, vs->client_pf.gshift); /* green-shift */ in pixel_format_message()
2347 vnc_write_u8(vs, vs->client_pf.bshift); /* blue-shift */ in pixel_format_message()
2351 vs->write_pixels = vnc_write_pixels_copy; in pixel_format_message()
2363 vs->client_width, in vnc_colordepth()
2364 vs->client_height, in vnc_colordepth()
2379 VncDisplay *vd = vs->vd; in protocol_client_msg()
2382 update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE); in protocol_client_msg()
2459 " in extended clipboard pseudo-encoding."); in protocol_client_msg()
2528 trace_vnc_msg_client_audio_enable(vs, vs->ioc); in protocol_client_msg()
2532 trace_vnc_msg_client_audio_disable(vs, vs->ioc); in protocol_client_msg()
2539 case 0: vs->as.fmt = AUDIO_FORMAT_U8; break; in protocol_client_msg()
2540 case 1: vs->as.fmt = AUDIO_FORMAT_S8; break; in protocol_client_msg()
2541 case 2: vs->as.fmt = AUDIO_FORMAT_U16; break; in protocol_client_msg()
2542 case 3: vs->as.fmt = AUDIO_FORMAT_S16; break; in protocol_client_msg()
2543 case 4: vs->as.fmt = AUDIO_FORMAT_U32; break; in protocol_client_msg()
2544 case 5: vs->as.fmt = AUDIO_FORMAT_S32; break; in protocol_client_msg()
2550 vs->as.nchannels = read_u8(data, 5); in protocol_client_msg()
2551 if (vs->as.nchannels != 1 && vs->as.nchannels != 2) { in protocol_client_msg()
2560 * protects calculations involving 'vs->as.freq' later. in protocol_client_msg()
2567 vs->as.freq = freq; in protocol_client_msg()
2569 vs, vs->ioc, vs->as.fmt, vs->as.nchannels, vs->as.freq); in protocol_client_msg()
2602 trace_vnc_msg_client_set_desktop_size(vs, vs->ioc, w, h, screens); in protocol_client_msg()
2603 if (dpy_ui_info_supported(vs->vd->dcl.con)) { in protocol_client_msg()
2608 dpy_set_ui_info(vs->vd->dcl.con, &info, false); in protocol_client_msg()
2634 switch (vs->vd->share_policy) { in protocol_client_init()
2656 QTAILQ_FOREACH(client, &vs->vd->clients, next) { in protocol_client_init()
2660 if (client->share_mode != VNC_SHARE_MODE_EXCLUSIVE && in protocol_client_init()
2661 client->share_mode != VNC_SHARE_MODE_SHARED) { in protocol_client_init()
2668 if (vs->vd->num_exclusive > 0) { in protocol_client_init()
2680 * someone forgetting to say -shared when running the vnc in protocol_client_init()
2691 if (vs->vd->num_shared > vs->vd->connections_limit) { in protocol_client_init()
2696 assert(pixman_image_get_width(vs->vd->server) < 65536 && in protocol_client_init()
2697 pixman_image_get_width(vs->vd->server) >= 0); in protocol_client_init()
2698 assert(pixman_image_get_height(vs->vd->server) < 65536 && in protocol_client_init()
2699 pixman_image_get_height(vs->vd->server) >= 0); in protocol_client_init()
2700 vs->client_width = pixman_image_get_width(vs->vd->server); in protocol_client_init()
2701 vs->client_height = pixman_image_get_height(vs->vd->server); in protocol_client_init()
2702 vnc_write_u16(vs, vs->client_width); in protocol_client_init()
2703 vnc_write_u16(vs, vs->client_height); in protocol_client_init()
2736 if (vs->minor >= 8) { in authentication_failed()
2767 if (!vs->vd->password) { in protocol_client_auth_vnc()
2768 trace_vnc_auth_fail(vs, vs->auth, "password is not set", ""); in protocol_client_auth_vnc()
2771 if (vs->vd->expires < now) { in protocol_client_auth_vnc()
2772 trace_vnc_auth_fail(vs, vs->auth, "password is expired", ""); in protocol_client_auth_vnc()
2776 memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE); in protocol_client_auth_vnc()
2779 pwlen = strlen(vs->vd->password); in protocol_client_auth_vnc()
2781 key[i] = i<pwlen ? vs->vd->password[i] : 0; in protocol_client_auth_vnc()
2790 trace_vnc_auth_fail(vs, vs->auth, "cannot create cipher", in protocol_client_auth_vnc()
2797 vs->challenge, in protocol_client_auth_vnc()
2801 trace_vnc_auth_fail(vs, vs->auth, "cannot encrypt challenge response", in protocol_client_auth_vnc()
2809 trace_vnc_auth_fail(vs, vs->auth, "mis-matched challenge response", ""); in protocol_client_auth_vnc()
2812 trace_vnc_auth_pass(vs, vs->auth); in protocol_client_auth_vnc()
2832 if (qcrypto_random_bytes(vs->challenge, sizeof(vs->challenge), &err)) { in start_auth_vnc()
2833 trace_vnc_auth_fail(vs, vs->auth, "cannot get random bytes", in start_auth_vnc()
2841 vnc_write(vs, vs->challenge, sizeof(vs->challenge)); in start_auth_vnc()
2844 vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge)); in start_auth_vnc()
2852 if (data[0] != vs->auth) { /* Reject auth */ in protocol_client_auth()
2853 trace_vnc_auth_reject(vs, vs->auth, (int)data[0]); in protocol_client_auth()
2856 trace_vnc_auth_start(vs, vs->auth); in protocol_client_auth()
2857 switch (vs->auth) { in protocol_client_auth()
2859 if (vs->minor >= 8) { in protocol_client_auth()
2863 trace_vnc_auth_pass(vs, vs->auth); in protocol_client_auth()
2882 trace_vnc_auth_fail(vs, vs->auth, "Unhandled auth method", ""); in protocol_client_auth()
2896 if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) { in protocol_version()
2901 VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor); in protocol_version()
2902 if (vs->major != 3 || in protocol_version()
2903 (vs->minor != 3 && in protocol_version()
2904 vs->minor != 4 && in protocol_version()
2905 vs->minor != 5 && in protocol_version()
2906 vs->minor != 7 && in protocol_version()
2907 vs->minor != 8)) { in protocol_version()
2917 if (vs->minor == 4 || vs->minor == 5) in protocol_version()
2918 vs->minor = 3; in protocol_version()
2920 if (vs->minor == 3) { in protocol_version()
2921 trace_vnc_auth_start(vs, vs->auth); in protocol_version()
2922 if (vs->auth == VNC_AUTH_NONE) { in protocol_version()
2923 vnc_write_u32(vs, vs->auth); in protocol_version()
2925 trace_vnc_auth_pass(vs, vs->auth); in protocol_version()
2927 } else if (vs->auth == VNC_AUTH_VNC) { in protocol_version()
2929 vnc_write_u32(vs, vs->auth); in protocol_version()
2933 trace_vnc_auth_fail(vs, vs->auth, in protocol_version()
2941 vnc_write_u8(vs, vs->auth); in protocol_version()
2951 struct VncSurface *vs = &vd->guest; in vnc_stat_rect()
2953 return &vs->stats[y / VNC_STAT_RECT][x / VNC_STAT_RECT]; in vnc_stat_rect()
2967 vs->lossy_rect[j][i] = 1; in vnc_sent_lossy_rect()
2982 QTAILQ_FOREACH(vs, &vd->clients, next) { in vnc_refresh_lossy_rect()
2985 /* kernel send buffers are full -> refresh later */ in vnc_refresh_lossy_rect()
2986 if (vs->output.offset) { in vnc_refresh_lossy_rect()
2990 if (!vs->lossy_rect[sty][stx]) { in vnc_refresh_lossy_rect()
2994 vs->lossy_rect[sty][stx] = 0; in vnc_refresh_lossy_rect()
2996 bitmap_set(vs->dirty[y + j], in vnc_refresh_lossy_rect()
3008 int width = MIN(pixman_image_get_width(vd->guest.fb), in vnc_update_stats()
3009 pixman_image_get_width(vd->server)); in vnc_update_stats()
3010 int height = MIN(pixman_image_get_height(vd->guest.fb), in vnc_update_stats()
3011 pixman_image_get_height(vd->server)); in vnc_update_stats()
3020 rect->updated = false; in vnc_update_stats()
3026 if (timercmp(&vd->guest.last_freq_check, &res, >)) { in vnc_update_stats()
3029 vd->guest.last_freq_check = *tv; in vnc_update_stats()
3034 int count = ARRAY_SIZE(rect->times); in vnc_update_stats()
3037 if (!timerisset(&rect->times[count - 1])) { in vnc_update_stats()
3041 max = rect->times[(rect->idx + count - 1) % count]; in vnc_update_stats()
3045 rect->freq = 0; in vnc_update_stats()
3047 memset(rect->times, 0, sizeof (rect->times)); in vnc_update_stats()
3051 min = rect->times[rect->idx]; in vnc_update_stats()
3052 max = rect->times[(rect->idx + count - 1) % count]; in vnc_update_stats()
3055 rect->freq = res.tv_sec + res.tv_usec / 1000000.; in vnc_update_stats()
3056 rect->freq /= count; in vnc_update_stats()
3057 rect->freq = 1. / rect->freq; in vnc_update_stats()
3074 total += vnc_stat_rect(vs->vd, i, j)->freq; in vnc_update_freq()
3091 if (rect->updated) { in vnc_rect_updated()
3094 rect->times[rect->idx] = *tv; in vnc_rect_updated()
3095 rect->idx = (rect->idx + 1) % ARRAY_SIZE(rect->times); in vnc_rect_updated()
3096 rect->updated = true; in vnc_rect_updated()
3101 int width = MIN(pixman_image_get_width(vd->guest.fb), in vnc_refresh_server_surface()
3102 pixman_image_get_width(vd->server)); in vnc_refresh_server_surface()
3103 int height = MIN(pixman_image_get_height(vd->guest.fb), in vnc_refresh_server_surface()
3104 pixman_image_get_height(vd->server)); in vnc_refresh_server_surface()
3116 if (!vd->non_adaptive) { in vnc_refresh_server_surface()
3121 offset = find_next_bit((unsigned long *) &vd->guest.dirty, in vnc_refresh_server_surface()
3122 height * VNC_DIRTY_BPL(&vd->guest), 0); in vnc_refresh_server_surface()
3123 if (offset == height * VNC_DIRTY_BPL(&vd->guest)) { in vnc_refresh_server_surface()
3133 server_row0 = (uint8_t *)pixman_image_get_data(vd->server); in vnc_refresh_server_surface()
3135 pixman_image_get_stride(vd->server); in vnc_refresh_server_surface()
3138 if (vd->guest.format != VNC_SERVER_FB_FORMAT) { in vnc_refresh_server_surface()
3139 int w = pixman_image_get_width(vd->server); in vnc_refresh_server_surface()
3143 PIXMAN_FORMAT_BPP(pixman_image_get_format(vd->guest.fb)); in vnc_refresh_server_surface()
3144 guest_row0 = (uint8_t *)pixman_image_get_data(vd->guest.fb); in vnc_refresh_server_surface()
3145 guest_stride = pixman_image_get_stride(vd->guest.fb); in vnc_refresh_server_surface()
3146 guest_ll = pixman_image_get_width(vd->guest.fb) in vnc_refresh_server_surface()
3152 y = offset / VNC_DIRTY_BPL(&vd->guest); in vnc_refresh_server_surface()
3153 x = offset % VNC_DIRTY_BPL(&vd->guest); in vnc_refresh_server_surface()
3157 if (vd->guest.format != VNC_SERVER_FB_FORMAT) { in vnc_refresh_server_surface()
3158 qemu_pixman_linebuf_fill(tmpbuf, vd->guest.fb, width, 0, y); in vnc_refresh_server_surface()
3168 if (!test_and_clear_bit(x, vd->guest.dirty[y])) { in vnc_refresh_server_surface()
3172 _cmp_bytes = line_bytes - x * cmp_bytes; in vnc_refresh_server_surface()
3179 if (!vd->non_adaptive) { in vnc_refresh_server_surface()
3183 QTAILQ_FOREACH(vs, &vd->clients, next) { in vnc_refresh_server_surface()
3184 set_bit(x, vs->dirty[y]); in vnc_refresh_server_surface()
3190 offset = find_next_bit((unsigned long *) &vd->guest.dirty, in vnc_refresh_server_surface()
3191 height * VNC_DIRTY_BPL(&vd->guest), in vnc_refresh_server_surface()
3192 y * VNC_DIRTY_BPL(&vd->guest)); in vnc_refresh_server_surface()
3193 if (offset == height * VNC_DIRTY_BPL(&vd->guest)) { in vnc_refresh_server_surface()
3208 if (QTAILQ_EMPTY(&vd->clients)) { in vnc_refresh()
3209 update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_MAX); in vnc_refresh()
3213 graphic_hw_update(vd->dcl.con); in vnc_refresh()
3216 update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE); in vnc_refresh()
3223 QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) { in vnc_refresh()
3229 vd->dcl.update_interval /= 2; in vnc_refresh()
3230 if (vd->dcl.update_interval < VNC_REFRESH_INTERVAL_BASE) { in vnc_refresh()
3231 vd->dcl.update_interval = VNC_REFRESH_INTERVAL_BASE; in vnc_refresh()
3234 vd->dcl.update_interval += VNC_REFRESH_INTERVAL_INC; in vnc_refresh()
3235 if (vd->dcl.update_interval > VNC_REFRESH_INTERVAL_MAX) { in vnc_refresh()
3236 vd->dcl.update_interval = VNC_REFRESH_INTERVAL_MAX; in vnc_refresh()
3245 bool first_client = QTAILQ_EMPTY(&vd->clients); in vnc_connect()
3249 vs->zrle = g_new0(VncZrle, 1); in vnc_connect()
3250 vs->tight = g_new0(VncTight, 1); in vnc_connect()
3251 vs->magic = VNC_MAGIC; in vnc_connect()
3252 vs->sioc = sioc; in vnc_connect()
3253 object_ref(OBJECT(vs->sioc)); in vnc_connect()
3254 vs->ioc = QIO_CHANNEL(sioc); in vnc_connect()
3255 object_ref(OBJECT(vs->ioc)); in vnc_connect()
3256 vs->vd = vd; in vnc_connect()
3258 buffer_init(&vs->input, "vnc-input/%p", sioc); in vnc_connect()
3259 buffer_init(&vs->output, "vnc-output/%p", sioc); in vnc_connect()
3260 buffer_init(&vs->jobs_buffer, "vnc-jobs_buffer/%p", sioc); in vnc_connect()
3262 buffer_init(&vs->tight->tight, "vnc-tight/%p", sioc); in vnc_connect()
3263 buffer_init(&vs->tight->zlib, "vnc-tight-zlib/%p", sioc); in vnc_connect()
3264 buffer_init(&vs->tight->gradient, "vnc-tight-gradient/%p", sioc); in vnc_connect()
3266 buffer_init(&vs->tight->jpeg, "vnc-tight-jpeg/%p", sioc); in vnc_connect()
3269 buffer_init(&vs->tight->png, "vnc-tight-png/%p", sioc); in vnc_connect()
3271 buffer_init(&vs->zlib.zlib, "vnc-zlib/%p", sioc); in vnc_connect()
3272 buffer_init(&vs->zrle->zrle, "vnc-zrle/%p", sioc); in vnc_connect()
3273 buffer_init(&vs->zrle->fb, "vnc-zrle-fb/%p", sioc); in vnc_connect()
3274 buffer_init(&vs->zrle->zlib, "vnc-zrle-zlib/%p", sioc); in vnc_connect()
3277 vs->auth = VNC_AUTH_NONE; in vnc_connect()
3278 vs->subauth = VNC_AUTH_INVALID; in vnc_connect()
3281 vs->auth = vd->ws_auth; in vnc_connect()
3282 vs->subauth = VNC_AUTH_INVALID; in vnc_connect()
3284 vs->auth = vd->auth; in vnc_connect()
3285 vs->subauth = vd->subauth; in vnc_connect()
3289 sioc, websocket, vs->auth, vs->subauth); in vnc_connect()
3291 vs->lossy_rect = g_malloc0(VNC_STAT_ROWS * sizeof (*vs->lossy_rect)); in vnc_connect()
3293 vs->lossy_rect[i] = g_new0(uint8_t, VNC_STAT_COLS); in vnc_connect()
3296 VNC_DEBUG("New client on socket %p\n", vs->sioc); in vnc_connect()
3297 update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE); in vnc_connect()
3298 qio_channel_set_blocking(vs->ioc, false, NULL); in vnc_connect()
3299 if (vs->ioc_tag) { in vnc_connect()
3300 g_source_remove(vs->ioc_tag); in vnc_connect()
3303 vs->websocket = 1; in vnc_connect()
3304 if (vd->tlscreds) { in vnc_connect()
3305 vs->ioc_tag = qio_channel_add_watch( in vnc_connect()
3306 vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR, in vnc_connect()
3309 vs->ioc_tag = qio_channel_add_watch( in vnc_connect()
3310 vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR, in vnc_connect()
3314 vs->ioc_tag = qio_channel_add_watch( in vnc_connect()
3315 vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR, in vnc_connect()
3323 vs->last_x = -1; in vnc_connect()
3324 vs->last_y = -1; in vnc_connect()
3326 vs->as.freq = 44100; in vnc_connect()
3327 vs->as.nchannels = 2; in vnc_connect()
3328 vs->as.fmt = AUDIO_FORMAT_S16; in vnc_connect()
3329 vs->as.endianness = 0; in vnc_connect()
3331 qemu_mutex_init(&vs->output_mutex); in vnc_connect()
3332 vs->bh = qemu_bh_new(vnc_jobs_bh, vs); in vnc_connect()
3334 QTAILQ_INSERT_TAIL(&vd->clients, vs, next); in vnc_connect()
3339 graphic_hw_update(vd->dcl.con); in vnc_connect()
3341 if (!vs->websocket) { in vnc_connect()
3345 if (vd->num_connecting > vd->connections_limit) { in vnc_connect()
3346 QTAILQ_FOREACH(vs, &vd->clients, next) { in vnc_connect()
3347 if (vs->share_mode == VNC_SHARE_MODE_CONNECTING) { in vnc_connect()
3361 vs->mouse_mode_notifier.notify = check_pointer_type_change; in vnc_start_protocol()
3362 qemu_add_mouse_mode_change_notifier(&vs->mouse_mode_notifier); in vnc_start_protocol()
3370 bool isWebsock = listener == vd->wslistener; in vnc_listen_io()
3373 isWebsock ? "vnc-ws-server" : "vnc-server"); in vnc_listen_io()
3397 vd->id = strdup(id); in vnc_display_init()
3400 QTAILQ_INIT(&vd->clients); in vnc_display_init()
3401 vd->expires = TIME_MAX; in vnc_display_init()
3405 vd->kbd_layout = init_keyboard_layout(name2keysym, in vnc_display_init()
3408 vd->kbd_layout = init_keyboard_layout(name2keysym, "en-us", errp); in vnc_display_init()
3411 if (!vd->kbd_layout) { in vnc_display_init()
3415 vd->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE; in vnc_display_init()
3416 vd->connections_limit = 32; in vnc_display_init()
3418 qemu_mutex_init(&vd->mutex); in vnc_display_init()
3421 vd->dcl.ops = &dcl_ops; in vnc_display_init()
3422 register_displaychangelistener(&vd->dcl); in vnc_display_init()
3423 vd->kbd = qkbd_state_init(vd->dcl.con); in vnc_display_init()
3433 if (vd->listener) { in vnc_display_close()
3434 qio_net_listener_disconnect(vd->listener); in vnc_display_close()
3435 object_unref(OBJECT(vd->listener)); in vnc_display_close()
3437 vd->listener = NULL; in vnc_display_close()
3439 if (vd->wslistener) { in vnc_display_close()
3440 qio_net_listener_disconnect(vd->wslistener); in vnc_display_close()
3441 object_unref(OBJECT(vd->wslistener)); in vnc_display_close()
3443 vd->wslistener = NULL; in vnc_display_close()
3445 vd->auth = VNC_AUTH_INVALID; in vnc_display_close()
3446 vd->subauth = VNC_AUTH_INVALID; in vnc_display_close()
3447 if (vd->tlscreds) { in vnc_display_close()
3448 object_unref(OBJECT(vd->tlscreds)); in vnc_display_close()
3449 vd->tlscreds = NULL; in vnc_display_close()
3451 if (vd->tlsauthz) { in vnc_display_close()
3452 object_unparent(OBJECT(vd->tlsauthz)); in vnc_display_close()
3453 vd->tlsauthz = NULL; in vnc_display_close()
3455 g_free(vd->tlsauthzid); in vnc_display_close()
3456 vd->tlsauthzid = NULL; in vnc_display_close()
3457 if (vd->lock_key_sync) { in vnc_display_close()
3458 qemu_remove_led_event_handler(vd->led); in vnc_display_close()
3459 vd->led = NULL; in vnc_display_close()
3462 if (vd->sasl.authz) { in vnc_display_close()
3463 object_unparent(OBJECT(vd->sasl.authz)); in vnc_display_close()
3464 vd->sasl.authz = NULL; in vnc_display_close()
3466 g_free(vd->sasl.authzid); in vnc_display_close()
3467 vd->sasl.authzid = NULL; in vnc_display_close()
3476 return -EINVAL; in vnc_display_password()
3478 if (vd->auth == VNC_AUTH_NONE) { in vnc_display_password()
3480 "password auth using '-vnc ${dpy},password'.\n"); in vnc_display_password()
3481 return -EINVAL; in vnc_display_password()
3484 g_free(vd->password); in vnc_display_password()
3485 vd->password = g_strdup(password); in vnc_display_password()
3495 return -EINVAL; in vnc_display_pw_expire()
3498 vd->expires = expires; in vnc_display_pw_expire()
3506 if (!vd->listener || !vd->listener->nsioc) { in vnc_display_print_local_addr()
3510 addr = qio_channel_socket_get_local_address(vd->listener->sioc[0], NULL); in vnc_display_print_local_addr()
3515 if (addr->type != SOCKET_ADDRESS_TYPE_INET) { in vnc_display_print_local_addr()
3520 addr->u.inet.host, in vnc_display_print_local_addr()
3521 addr->u.inet.port); in vnc_display_print_local_addr()
3537 .name = "tls-creds",
3564 .name = "password-secret",
3570 .name = "lock-key-sync",
3573 .name = "key-delay-ms",
3579 .name = "tls-authz",
3582 .name = "sasl-authz",
3588 .name = "non-adaptive",
3594 .name = "power-control",
3643 * sub-auth types. in vnc_display_setup_auth()
3651 * meaning combinations 4->6 and 7->9 will be mapped to in vnc_display_setup_auth()
3652 * VNC auth schemes in the same way as combos 1->3. in vnc_display_setup_auth()
3680 return -1; in vnc_display_setup_auth()
3726 int ret = -1; in vnc_display_get_address()
3732 addr->type = SOCKET_ADDRESS_TYPE_UNIX; in vnc_display_get_address()
3733 addr->u.q_unix.path = g_strdup(addrstr + 5); in vnc_display_get_address()
3756 hostlen = port - addrstr; in vnc_display_get_address()
3764 addr->type = SOCKET_ADDRESS_TYPE_INET; in vnc_display_get_address()
3765 inet = &addr->u.inet; in vnc_display_get_address()
3766 if (hostlen && addrstr[0] == '[' && addrstr[hostlen - 1] == ']') { in vnc_display_get_address()
3767 inet->host = g_strndup(addrstr + 1, hostlen - 2); in vnc_display_get_address()
3769 inet->host = g_strndup(addrstr, hostlen); in vnc_display_get_address()
3776 if (displaynum == -1) { in vnc_display_get_address()
3780 inet->port = g_strdup_printf( in vnc_display_get_address()
3783 inet->has_to = true; in vnc_display_get_address()
3784 inet->to = to + 5700; in vnc_display_get_address()
3787 inet->port = g_strdup(port); in vnc_display_get_address()
3800 inet->port = g_strdup_printf( in vnc_display_get_address()
3804 inet->has_to = true; in vnc_display_get_address()
3805 inet->to = to + offset; in vnc_display_get_address()
3809 inet->ipv4 = ipv4; in vnc_display_get_address()
3810 inet->has_ipv4 = has_ipv4; in vnc_display_get_address()
3811 inet->ipv6 = ipv6; in vnc_display_get_address()
3812 inet->has_ipv6 = has_ipv6; in vnc_display_get_address()
3846 int displaynum = -1; in vnc_display_get_addresses()
3856 return -1; in vnc_display_get_addresses()
3867 return -1; in vnc_display_get_addresses()
3869 /* Historical compat - first listen address can be used in vnc_display_get_addresses()
3872 if (displaynum == -1) { in vnc_display_get_addresses()
3878 if (saddr_list && !saddr_list->next) { in vnc_display_get_addresses()
3879 single_saddr = saddr_list->value; in vnc_display_get_addresses()
3885 displaynum = -1; in vnc_display_get_addresses()
3894 return -1; in vnc_display_get_addresses()
3897 /* Historical compat - if only a single listen address was in vnc_display_get_addresses()
3902 single_saddr->type == SOCKET_ADDRESS_TYPE_INET && in vnc_display_get_addresses()
3903 wsaddr->type == SOCKET_ADDRESS_TYPE_INET && in vnc_display_get_addresses()
3904 g_str_equal(wsaddr->u.inet.host, "") && in vnc_display_get_addresses()
3905 !g_str_equal(single_saddr->u.inet.host, "")) { in vnc_display_get_addresses()
3906 g_free(wsaddr->u.inet.host); in vnc_display_get_addresses()
3907 wsaddr->u.inet.host = g_strdup(single_saddr->u.inet.host); in vnc_display_get_addresses()
3927 return -1; in vnc_display_connect()
3929 if (!saddr_list || saddr_list->next) { in vnc_display_connect()
3931 return -1; in vnc_display_connect()
3934 qio_channel_set_name(QIO_CHANNEL(sioc), "vnc-reverse"); in vnc_display_connect()
3935 if (qio_channel_socket_connect_sync(sioc, saddr_list->value, errp) < 0) { in vnc_display_connect()
3937 return -1; in vnc_display_connect()
3953 vd->listener = qio_net_listener_new(); in vnc_display_listen()
3954 qio_net_listener_set_name(vd->listener, "vnc-listen"); in vnc_display_listen()
3955 for (el = saddr_list; el; el = el->next) { in vnc_display_listen()
3956 if (qio_net_listener_open_sync(vd->listener, in vnc_display_listen()
3957 el->value, 1, in vnc_display_listen()
3959 return -1; in vnc_display_listen()
3963 qio_net_listener_set_client_func(vd->listener, in vnc_display_listen()
3968 vd->wslistener = qio_net_listener_new(); in vnc_display_listen()
3969 qio_net_listener_set_name(vd->wslistener, "vnc-ws-listen"); in vnc_display_listen()
3970 for (el = wsaddr_list; el; el = el->next) { in vnc_display_listen()
3971 if (qio_net_listener_open_sync(vd->wslistener, in vnc_display_listen()
3972 el->value, 1, in vnc_display_listen()
3974 return -1; in vnc_display_listen()
3978 qio_net_listener_set_client_func(vd->wslistener, in vnc_display_listen()
3994 if (arg->has_addresses) { in vnc_display_update()
3995 if (vd->listener) { in vnc_display_update()
3996 qio_net_listener_disconnect(vd->listener); in vnc_display_update()
3997 object_unref(OBJECT(vd->listener)); in vnc_display_update()
3998 vd->listener = NULL; in vnc_display_update()
4001 if (vnc_display_listen(vd, arg->addresses, NULL, errp) < 0) { in vnc_display_update()
4045 passwordSecret = qemu_opt_get(opts, "password-secret"); in vnc_display_open()
4049 "'password' flag is redundant with 'password-secret'"); in vnc_display_open()
4052 vd->password = qcrypto_secret_lookup_as_utf8(passwordSecret, in vnc_display_open()
4054 if (!vd->password) { in vnc_display_open()
4070 lock_key_sync = qemu_opt_get_bool(opts, "lock-key-sync", true); in vnc_display_open()
4071 key_delay_ms = qemu_opt_get_number(opts, "key-delay-ms", 10); in vnc_display_open()
4075 error_setg(errp, "VNC SASL auth requires cyrus-sasl support"); in vnc_display_open()
4079 credid = qemu_opt_get(opts, "tls-creds"); in vnc_display_open()
4089 vd->tlscreds = (QCryptoTLSCreds *) in vnc_display_open()
4092 if (!vd->tlscreds) { in vnc_display_open()
4097 object_ref(OBJECT(vd->tlscreds)); in vnc_display_open()
4099 if (!qcrypto_tls_creds_check_endpoint(vd->tlscreds, in vnc_display_open()
4105 tlsauthz = qemu_opt_get(opts, "tls-authz"); in vnc_display_open()
4106 if (tlsauthz && !vd->tlscreds) { in vnc_display_open()
4107 error_setg(errp, "'tls-authz' provided but TLS is not enabled"); in vnc_display_open()
4111 saslauthz = qemu_opt_get(opts, "sasl-authz"); in vnc_display_open()
4113 error_setg(errp, "'sasl-authz' provided but SASL auth is not enabled"); in vnc_display_open()
4120 vd->share_policy = VNC_SHARE_POLICY_IGNORE; in vnc_display_open()
4121 } else if (strcmp(share, "allow-exclusive") == 0) { in vnc_display_open()
4122 vd->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE; in vnc_display_open()
4123 } else if (strcmp(share, "force-shared") == 0) { in vnc_display_open()
4124 vd->share_policy = VNC_SHARE_POLICY_FORCE_SHARED; in vnc_display_open()
4130 vd->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE; in vnc_display_open()
4132 vd->connections_limit = qemu_opt_get_number(opts, "connections", 32); in vnc_display_open()
4135 vd->lossy = qemu_opt_get_bool(opts, "lossy", false); in vnc_display_open()
4137 vd->non_adaptive = qemu_opt_get_bool(opts, "non-adaptive", false); in vnc_display_open()
4141 if (!vd->lossy) { in vnc_display_open()
4142 vd->non_adaptive = true; in vnc_display_open()
4145 vd->power_control = qemu_opt_get_bool(opts, "power-control", false); in vnc_display_open()
4148 vd->tlsauthzid = g_strdup(tlsauthz); in vnc_display_open()
4153 vd->sasl.authzid = g_strdup(saslauthz); in vnc_display_open()
4158 if (vnc_display_setup_auth(&vd->auth, &vd->subauth, in vnc_display_open()
4159 vd->tlscreds, password, in vnc_display_open()
4163 trace_vnc_auth_init(vd, 0, vd->auth, vd->subauth); in vnc_display_open()
4165 if (vnc_display_setup_auth(&vd->ws_auth, &vd->ws_subauth, in vnc_display_open()
4166 vd->tlscreds, password, in vnc_display_open()
4170 trace_vnc_auth_init(vd, 1, vd->ws_auth, vd->ws_subauth); in vnc_display_open()
4177 vd->lock_key_sync = lock_key_sync; in vnc_display_open()
4179 vd->led = qemu_add_led_event_handler(kbd_leds, vd); in vnc_display_open()
4181 vd->ledstate = 0; in vnc_display_open()
4185 vd->audio_state = audio_state_by_name(audiodev, errp); in vnc_display_open()
4186 if (!vd->audio_state) { in vnc_display_open()
4190 vd->audio_state = audio_get_default_audio_state(NULL); in vnc_display_open()
4207 if (con != vd->dcl.con) { in vnc_display_open()
4208 qkbd_state_free(vd->kbd); in vnc_display_open()
4209 unregister_displaychangelistener(&vd->dcl); in vnc_display_open()
4210 vd->dcl.con = con; in vnc_display_open()
4211 register_displaychangelistener(&vd->dcl); in vnc_display_open()
4212 vd->kbd = qkbd_state_init(vd->dcl.con); in vnc_display_open()
4214 qkbd_state_set_delay(vd->kbd, key_delay_ms); in vnc_display_open()
4252 qio_channel_set_name(QIO_CHANNEL(sioc), "vnc-server"); in vnc_display_add_client()
4283 /* auto-assign id if not present */ in vnc_parse()
4297 return -1; in vnc_init_func()
4302 return -1; in vnc_init_func()