1*3e230dd2SCorentin Chary /* 2*3e230dd2SCorentin Chary * QEMU VNC display driver 3*3e230dd2SCorentin Chary * 4*3e230dd2SCorentin Chary * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws> 5*3e230dd2SCorentin Chary * Copyright (C) 2006 Fabrice Bellard 6*3e230dd2SCorentin Chary * Copyright (C) 2009 Red Hat, Inc 7*3e230dd2SCorentin Chary * 8*3e230dd2SCorentin Chary * Permission is hereby granted, free of charge, to any person obtaining a copy 9*3e230dd2SCorentin Chary * of this software and associated documentation files (the "Software"), to deal 10*3e230dd2SCorentin Chary * in the Software without restriction, including without limitation the rights 11*3e230dd2SCorentin Chary * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12*3e230dd2SCorentin Chary * copies of the Software, and to permit persons to whom the Software is 13*3e230dd2SCorentin Chary * furnished to do so, subject to the following conditions: 14*3e230dd2SCorentin Chary * 15*3e230dd2SCorentin Chary * The above copyright notice and this permission notice shall be included in 16*3e230dd2SCorentin Chary * all copies or substantial portions of the Software. 17*3e230dd2SCorentin Chary * 18*3e230dd2SCorentin Chary * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19*3e230dd2SCorentin Chary * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20*3e230dd2SCorentin Chary * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21*3e230dd2SCorentin Chary * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22*3e230dd2SCorentin Chary * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23*3e230dd2SCorentin Chary * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24*3e230dd2SCorentin Chary * THE SOFTWARE. 25*3e230dd2SCorentin Chary */ 26*3e230dd2SCorentin Chary 27*3e230dd2SCorentin Chary #include "vnc.h" 28*3e230dd2SCorentin Chary #include "sysemu.h" 29*3e230dd2SCorentin Chary #include "qemu_socket.h" 30*3e230dd2SCorentin Chary #include "qemu-timer.h" 31*3e230dd2SCorentin Chary #include "acl.h" 32*3e230dd2SCorentin Chary #include "qemu-objects.h" 33*3e230dd2SCorentin Chary 34*3e230dd2SCorentin Chary #define VNC_REFRESH_INTERVAL_BASE 30 35*3e230dd2SCorentin Chary #define VNC_REFRESH_INTERVAL_INC 50 36*3e230dd2SCorentin Chary #define VNC_REFRESH_INTERVAL_MAX 2000 37*3e230dd2SCorentin Chary 38*3e230dd2SCorentin Chary #include "vnc_keysym.h" 39*3e230dd2SCorentin Chary #include "d3des.h" 40*3e230dd2SCorentin Chary 41*3e230dd2SCorentin Chary #define count_bits(c, v) { \ 42*3e230dd2SCorentin Chary for (c = 0; v; v >>= 1) \ 43*3e230dd2SCorentin Chary { \ 44*3e230dd2SCorentin Chary c += v & 1; \ 45*3e230dd2SCorentin Chary } \ 46*3e230dd2SCorentin Chary } 47*3e230dd2SCorentin Chary 48*3e230dd2SCorentin Chary 49*3e230dd2SCorentin Chary static VncDisplay *vnc_display; /* needed for info vnc */ 50*3e230dd2SCorentin Chary static DisplayChangeListener *dcl; 51*3e230dd2SCorentin Chary 52*3e230dd2SCorentin Chary static int vnc_cursor_define(VncState *vs); 53*3e230dd2SCorentin Chary 54*3e230dd2SCorentin Chary static char *addr_to_string(const char *format, 55*3e230dd2SCorentin Chary struct sockaddr_storage *sa, 56*3e230dd2SCorentin Chary socklen_t salen) { 57*3e230dd2SCorentin Chary char *addr; 58*3e230dd2SCorentin Chary char host[NI_MAXHOST]; 59*3e230dd2SCorentin Chary char serv[NI_MAXSERV]; 60*3e230dd2SCorentin Chary int err; 61*3e230dd2SCorentin Chary size_t addrlen; 62*3e230dd2SCorentin Chary 63*3e230dd2SCorentin Chary if ((err = getnameinfo((struct sockaddr *)sa, salen, 64*3e230dd2SCorentin Chary host, sizeof(host), 65*3e230dd2SCorentin Chary serv, sizeof(serv), 66*3e230dd2SCorentin Chary NI_NUMERICHOST | NI_NUMERICSERV)) != 0) { 67*3e230dd2SCorentin Chary VNC_DEBUG("Cannot resolve address %d: %s\n", 68*3e230dd2SCorentin Chary err, gai_strerror(err)); 69*3e230dd2SCorentin Chary return NULL; 70*3e230dd2SCorentin Chary } 71*3e230dd2SCorentin Chary 72*3e230dd2SCorentin Chary /* Enough for the existing format + the 2 vars we're 73*3e230dd2SCorentin Chary * substituting in. */ 74*3e230dd2SCorentin Chary addrlen = strlen(format) + strlen(host) + strlen(serv); 75*3e230dd2SCorentin Chary addr = qemu_malloc(addrlen + 1); 76*3e230dd2SCorentin Chary snprintf(addr, addrlen, format, host, serv); 77*3e230dd2SCorentin Chary addr[addrlen] = '\0'; 78*3e230dd2SCorentin Chary 79*3e230dd2SCorentin Chary return addr; 80*3e230dd2SCorentin Chary } 81*3e230dd2SCorentin Chary 82*3e230dd2SCorentin Chary 83*3e230dd2SCorentin Chary char *vnc_socket_local_addr(const char *format, int fd) { 84*3e230dd2SCorentin Chary struct sockaddr_storage sa; 85*3e230dd2SCorentin Chary socklen_t salen; 86*3e230dd2SCorentin Chary 87*3e230dd2SCorentin Chary salen = sizeof(sa); 88*3e230dd2SCorentin Chary if (getsockname(fd, (struct sockaddr*)&sa, &salen) < 0) 89*3e230dd2SCorentin Chary return NULL; 90*3e230dd2SCorentin Chary 91*3e230dd2SCorentin Chary return addr_to_string(format, &sa, salen); 92*3e230dd2SCorentin Chary } 93*3e230dd2SCorentin Chary 94*3e230dd2SCorentin Chary char *vnc_socket_remote_addr(const char *format, int fd) { 95*3e230dd2SCorentin Chary struct sockaddr_storage sa; 96*3e230dd2SCorentin Chary socklen_t salen; 97*3e230dd2SCorentin Chary 98*3e230dd2SCorentin Chary salen = sizeof(sa); 99*3e230dd2SCorentin Chary if (getpeername(fd, (struct sockaddr*)&sa, &salen) < 0) 100*3e230dd2SCorentin Chary return NULL; 101*3e230dd2SCorentin Chary 102*3e230dd2SCorentin Chary return addr_to_string(format, &sa, salen); 103*3e230dd2SCorentin Chary } 104*3e230dd2SCorentin Chary 105*3e230dd2SCorentin Chary static int put_addr_qdict(QDict *qdict, struct sockaddr_storage *sa, 106*3e230dd2SCorentin Chary socklen_t salen) 107*3e230dd2SCorentin Chary { 108*3e230dd2SCorentin Chary char host[NI_MAXHOST]; 109*3e230dd2SCorentin Chary char serv[NI_MAXSERV]; 110*3e230dd2SCorentin Chary int err; 111*3e230dd2SCorentin Chary 112*3e230dd2SCorentin Chary if ((err = getnameinfo((struct sockaddr *)sa, salen, 113*3e230dd2SCorentin Chary host, sizeof(host), 114*3e230dd2SCorentin Chary serv, sizeof(serv), 115*3e230dd2SCorentin Chary NI_NUMERICHOST | NI_NUMERICSERV)) != 0) { 116*3e230dd2SCorentin Chary VNC_DEBUG("Cannot resolve address %d: %s\n", 117*3e230dd2SCorentin Chary err, gai_strerror(err)); 118*3e230dd2SCorentin Chary return -1; 119*3e230dd2SCorentin Chary } 120*3e230dd2SCorentin Chary 121*3e230dd2SCorentin Chary qdict_put(qdict, "host", qstring_from_str(host)); 122*3e230dd2SCorentin Chary qdict_put(qdict, "service", qstring_from_str(serv)); 123*3e230dd2SCorentin Chary qdict_put(qdict, "family",qstring_from_str(inet_strfamily(sa->ss_family))); 124*3e230dd2SCorentin Chary 125*3e230dd2SCorentin Chary return 0; 126*3e230dd2SCorentin Chary } 127*3e230dd2SCorentin Chary 128*3e230dd2SCorentin Chary static int vnc_server_addr_put(QDict *qdict, int fd) 129*3e230dd2SCorentin Chary { 130*3e230dd2SCorentin Chary struct sockaddr_storage sa; 131*3e230dd2SCorentin Chary socklen_t salen; 132*3e230dd2SCorentin Chary 133*3e230dd2SCorentin Chary salen = sizeof(sa); 134*3e230dd2SCorentin Chary if (getsockname(fd, (struct sockaddr*)&sa, &salen) < 0) { 135*3e230dd2SCorentin Chary return -1; 136*3e230dd2SCorentin Chary } 137*3e230dd2SCorentin Chary 138*3e230dd2SCorentin Chary return put_addr_qdict(qdict, &sa, salen); 139*3e230dd2SCorentin Chary } 140*3e230dd2SCorentin Chary 141*3e230dd2SCorentin Chary static int vnc_qdict_remote_addr(QDict *qdict, int fd) 142*3e230dd2SCorentin Chary { 143*3e230dd2SCorentin Chary struct sockaddr_storage sa; 144*3e230dd2SCorentin Chary socklen_t salen; 145*3e230dd2SCorentin Chary 146*3e230dd2SCorentin Chary salen = sizeof(sa); 147*3e230dd2SCorentin Chary if (getpeername(fd, (struct sockaddr*)&sa, &salen) < 0) { 148*3e230dd2SCorentin Chary return -1; 149*3e230dd2SCorentin Chary } 150*3e230dd2SCorentin Chary 151*3e230dd2SCorentin Chary return put_addr_qdict(qdict, &sa, salen); 152*3e230dd2SCorentin Chary } 153*3e230dd2SCorentin Chary 154*3e230dd2SCorentin Chary static const char *vnc_auth_name(VncDisplay *vd) { 155*3e230dd2SCorentin Chary switch (vd->auth) { 156*3e230dd2SCorentin Chary case VNC_AUTH_INVALID: 157*3e230dd2SCorentin Chary return "invalid"; 158*3e230dd2SCorentin Chary case VNC_AUTH_NONE: 159*3e230dd2SCorentin Chary return "none"; 160*3e230dd2SCorentin Chary case VNC_AUTH_VNC: 161*3e230dd2SCorentin Chary return "vnc"; 162*3e230dd2SCorentin Chary case VNC_AUTH_RA2: 163*3e230dd2SCorentin Chary return "ra2"; 164*3e230dd2SCorentin Chary case VNC_AUTH_RA2NE: 165*3e230dd2SCorentin Chary return "ra2ne"; 166*3e230dd2SCorentin Chary case VNC_AUTH_TIGHT: 167*3e230dd2SCorentin Chary return "tight"; 168*3e230dd2SCorentin Chary case VNC_AUTH_ULTRA: 169*3e230dd2SCorentin Chary return "ultra"; 170*3e230dd2SCorentin Chary case VNC_AUTH_TLS: 171*3e230dd2SCorentin Chary return "tls"; 172*3e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT: 173*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 174*3e230dd2SCorentin Chary switch (vd->subauth) { 175*3e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT_PLAIN: 176*3e230dd2SCorentin Chary return "vencrypt+plain"; 177*3e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT_TLSNONE: 178*3e230dd2SCorentin Chary return "vencrypt+tls+none"; 179*3e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT_TLSVNC: 180*3e230dd2SCorentin Chary return "vencrypt+tls+vnc"; 181*3e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT_TLSPLAIN: 182*3e230dd2SCorentin Chary return "vencrypt+tls+plain"; 183*3e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT_X509NONE: 184*3e230dd2SCorentin Chary return "vencrypt+x509+none"; 185*3e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT_X509VNC: 186*3e230dd2SCorentin Chary return "vencrypt+x509+vnc"; 187*3e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT_X509PLAIN: 188*3e230dd2SCorentin Chary return "vencrypt+x509+plain"; 189*3e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT_TLSSASL: 190*3e230dd2SCorentin Chary return "vencrypt+tls+sasl"; 191*3e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT_X509SASL: 192*3e230dd2SCorentin Chary return "vencrypt+x509+sasl"; 193*3e230dd2SCorentin Chary default: 194*3e230dd2SCorentin Chary return "vencrypt"; 195*3e230dd2SCorentin Chary } 196*3e230dd2SCorentin Chary #else 197*3e230dd2SCorentin Chary return "vencrypt"; 198*3e230dd2SCorentin Chary #endif 199*3e230dd2SCorentin Chary case VNC_AUTH_SASL: 200*3e230dd2SCorentin Chary return "sasl"; 201*3e230dd2SCorentin Chary } 202*3e230dd2SCorentin Chary return "unknown"; 203*3e230dd2SCorentin Chary } 204*3e230dd2SCorentin Chary 205*3e230dd2SCorentin Chary static int vnc_server_info_put(QDict *qdict) 206*3e230dd2SCorentin Chary { 207*3e230dd2SCorentin Chary if (vnc_server_addr_put(qdict, vnc_display->lsock) < 0) { 208*3e230dd2SCorentin Chary return -1; 209*3e230dd2SCorentin Chary } 210*3e230dd2SCorentin Chary 211*3e230dd2SCorentin Chary qdict_put(qdict, "auth", qstring_from_str(vnc_auth_name(vnc_display))); 212*3e230dd2SCorentin Chary return 0; 213*3e230dd2SCorentin Chary } 214*3e230dd2SCorentin Chary 215*3e230dd2SCorentin Chary static void vnc_client_cache_auth(VncState *client) 216*3e230dd2SCorentin Chary { 217*3e230dd2SCorentin Chary QDict *qdict; 218*3e230dd2SCorentin Chary 219*3e230dd2SCorentin Chary if (!client->info) { 220*3e230dd2SCorentin Chary return; 221*3e230dd2SCorentin Chary } 222*3e230dd2SCorentin Chary 223*3e230dd2SCorentin Chary qdict = qobject_to_qdict(client->info); 224*3e230dd2SCorentin Chary 225*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 226*3e230dd2SCorentin Chary if (client->tls.session && 227*3e230dd2SCorentin Chary client->tls.dname) { 228*3e230dd2SCorentin Chary qdict_put(qdict, "x509_dname", qstring_from_str(client->tls.dname)); 229*3e230dd2SCorentin Chary } 230*3e230dd2SCorentin Chary #endif 231*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL 232*3e230dd2SCorentin Chary if (client->sasl.conn && 233*3e230dd2SCorentin Chary client->sasl.username) { 234*3e230dd2SCorentin Chary qdict_put(qdict, "sasl_username", 235*3e230dd2SCorentin Chary qstring_from_str(client->sasl.username)); 236*3e230dd2SCorentin Chary } 237*3e230dd2SCorentin Chary #endif 238*3e230dd2SCorentin Chary } 239*3e230dd2SCorentin Chary 240*3e230dd2SCorentin Chary static void vnc_client_cache_addr(VncState *client) 241*3e230dd2SCorentin Chary { 242*3e230dd2SCorentin Chary QDict *qdict; 243*3e230dd2SCorentin Chary 244*3e230dd2SCorentin Chary qdict = qdict_new(); 245*3e230dd2SCorentin Chary if (vnc_qdict_remote_addr(qdict, client->csock) < 0) { 246*3e230dd2SCorentin Chary QDECREF(qdict); 247*3e230dd2SCorentin Chary /* XXX: how to report the error? */ 248*3e230dd2SCorentin Chary return; 249*3e230dd2SCorentin Chary } 250*3e230dd2SCorentin Chary 251*3e230dd2SCorentin Chary client->info = QOBJECT(qdict); 252*3e230dd2SCorentin Chary } 253*3e230dd2SCorentin Chary 254*3e230dd2SCorentin Chary static void vnc_qmp_event(VncState *vs, MonitorEvent event) 255*3e230dd2SCorentin Chary { 256*3e230dd2SCorentin Chary QDict *server; 257*3e230dd2SCorentin Chary QObject *data; 258*3e230dd2SCorentin Chary 259*3e230dd2SCorentin Chary if (!vs->info) { 260*3e230dd2SCorentin Chary return; 261*3e230dd2SCorentin Chary } 262*3e230dd2SCorentin Chary 263*3e230dd2SCorentin Chary server = qdict_new(); 264*3e230dd2SCorentin Chary if (vnc_server_info_put(server) < 0) { 265*3e230dd2SCorentin Chary QDECREF(server); 266*3e230dd2SCorentin Chary return; 267*3e230dd2SCorentin Chary } 268*3e230dd2SCorentin Chary 269*3e230dd2SCorentin Chary data = qobject_from_jsonf("{ 'client': %p, 'server': %p }", 270*3e230dd2SCorentin Chary vs->info, QOBJECT(server)); 271*3e230dd2SCorentin Chary 272*3e230dd2SCorentin Chary monitor_protocol_event(event, data); 273*3e230dd2SCorentin Chary 274*3e230dd2SCorentin Chary qobject_incref(vs->info); 275*3e230dd2SCorentin Chary qobject_decref(data); 276*3e230dd2SCorentin Chary } 277*3e230dd2SCorentin Chary 278*3e230dd2SCorentin Chary static void info_vnc_iter(QObject *obj, void *opaque) 279*3e230dd2SCorentin Chary { 280*3e230dd2SCorentin Chary QDict *client; 281*3e230dd2SCorentin Chary Monitor *mon = opaque; 282*3e230dd2SCorentin Chary 283*3e230dd2SCorentin Chary client = qobject_to_qdict(obj); 284*3e230dd2SCorentin Chary monitor_printf(mon, "Client:\n"); 285*3e230dd2SCorentin Chary monitor_printf(mon, " address: %s:%s\n", 286*3e230dd2SCorentin Chary qdict_get_str(client, "host"), 287*3e230dd2SCorentin Chary qdict_get_str(client, "service")); 288*3e230dd2SCorentin Chary 289*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 290*3e230dd2SCorentin Chary monitor_printf(mon, " x509_dname: %s\n", 291*3e230dd2SCorentin Chary qdict_haskey(client, "x509_dname") ? 292*3e230dd2SCorentin Chary qdict_get_str(client, "x509_dname") : "none"); 293*3e230dd2SCorentin Chary #endif 294*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL 295*3e230dd2SCorentin Chary monitor_printf(mon, " username: %s\n", 296*3e230dd2SCorentin Chary qdict_haskey(client, "sasl_username") ? 297*3e230dd2SCorentin Chary qdict_get_str(client, "sasl_username") : "none"); 298*3e230dd2SCorentin Chary #endif 299*3e230dd2SCorentin Chary } 300*3e230dd2SCorentin Chary 301*3e230dd2SCorentin Chary void do_info_vnc_print(Monitor *mon, const QObject *data) 302*3e230dd2SCorentin Chary { 303*3e230dd2SCorentin Chary QDict *server; 304*3e230dd2SCorentin Chary QList *clients; 305*3e230dd2SCorentin Chary 306*3e230dd2SCorentin Chary server = qobject_to_qdict(data); 307*3e230dd2SCorentin Chary if (qdict_get_bool(server, "enabled") == 0) { 308*3e230dd2SCorentin Chary monitor_printf(mon, "Server: disabled\n"); 309*3e230dd2SCorentin Chary return; 310*3e230dd2SCorentin Chary } 311*3e230dd2SCorentin Chary 312*3e230dd2SCorentin Chary monitor_printf(mon, "Server:\n"); 313*3e230dd2SCorentin Chary monitor_printf(mon, " address: %s:%s\n", 314*3e230dd2SCorentin Chary qdict_get_str(server, "host"), 315*3e230dd2SCorentin Chary qdict_get_str(server, "service")); 316*3e230dd2SCorentin Chary monitor_printf(mon, " auth: %s\n", qdict_get_str(server, "auth")); 317*3e230dd2SCorentin Chary 318*3e230dd2SCorentin Chary clients = qdict_get_qlist(server, "clients"); 319*3e230dd2SCorentin Chary if (qlist_empty(clients)) { 320*3e230dd2SCorentin Chary monitor_printf(mon, "Client: none\n"); 321*3e230dd2SCorentin Chary } else { 322*3e230dd2SCorentin Chary qlist_iter(clients, info_vnc_iter, mon); 323*3e230dd2SCorentin Chary } 324*3e230dd2SCorentin Chary } 325*3e230dd2SCorentin Chary 326*3e230dd2SCorentin Chary void do_info_vnc(Monitor *mon, QObject **ret_data) 327*3e230dd2SCorentin Chary { 328*3e230dd2SCorentin Chary if (vnc_display == NULL || vnc_display->display == NULL) { 329*3e230dd2SCorentin Chary *ret_data = qobject_from_jsonf("{ 'enabled': false }"); 330*3e230dd2SCorentin Chary } else { 331*3e230dd2SCorentin Chary QList *clist; 332*3e230dd2SCorentin Chary VncState *client; 333*3e230dd2SCorentin Chary 334*3e230dd2SCorentin Chary clist = qlist_new(); 335*3e230dd2SCorentin Chary QTAILQ_FOREACH(client, &vnc_display->clients, next) { 336*3e230dd2SCorentin Chary if (client->info) { 337*3e230dd2SCorentin Chary /* incref so that it's not freed by upper layers */ 338*3e230dd2SCorentin Chary qobject_incref(client->info); 339*3e230dd2SCorentin Chary qlist_append_obj(clist, client->info); 340*3e230dd2SCorentin Chary } 341*3e230dd2SCorentin Chary } 342*3e230dd2SCorentin Chary 343*3e230dd2SCorentin Chary *ret_data = qobject_from_jsonf("{ 'enabled': true, 'clients': %p }", 344*3e230dd2SCorentin Chary QOBJECT(clist)); 345*3e230dd2SCorentin Chary assert(*ret_data != NULL); 346*3e230dd2SCorentin Chary 347*3e230dd2SCorentin Chary if (vnc_server_info_put(qobject_to_qdict(*ret_data)) < 0) { 348*3e230dd2SCorentin Chary qobject_decref(*ret_data); 349*3e230dd2SCorentin Chary *ret_data = NULL; 350*3e230dd2SCorentin Chary } 351*3e230dd2SCorentin Chary } 352*3e230dd2SCorentin Chary } 353*3e230dd2SCorentin Chary 354*3e230dd2SCorentin Chary static inline uint32_t vnc_has_feature(VncState *vs, int feature) { 355*3e230dd2SCorentin Chary return (vs->features & (1 << feature)); 356*3e230dd2SCorentin Chary } 357*3e230dd2SCorentin Chary 358*3e230dd2SCorentin Chary /* TODO 359*3e230dd2SCorentin Chary 1) Get the queue working for IO. 360*3e230dd2SCorentin Chary 2) there is some weirdness when using the -S option (the screen is grey 361*3e230dd2SCorentin Chary and not totally invalidated 362*3e230dd2SCorentin Chary 3) resolutions > 1024 363*3e230dd2SCorentin Chary */ 364*3e230dd2SCorentin Chary 365*3e230dd2SCorentin Chary static int vnc_update_client(VncState *vs, int has_dirty); 366*3e230dd2SCorentin Chary static void vnc_disconnect_start(VncState *vs); 367*3e230dd2SCorentin Chary static void vnc_disconnect_finish(VncState *vs); 368*3e230dd2SCorentin Chary static void vnc_init_timer(VncDisplay *vd); 369*3e230dd2SCorentin Chary static void vnc_remove_timer(VncDisplay *vd); 370*3e230dd2SCorentin Chary 371*3e230dd2SCorentin Chary static void vnc_colordepth(VncState *vs); 372*3e230dd2SCorentin Chary static void framebuffer_update_request(VncState *vs, int incremental, 373*3e230dd2SCorentin Chary int x_position, int y_position, 374*3e230dd2SCorentin Chary int w, int h); 375*3e230dd2SCorentin Chary static void vnc_refresh(void *opaque); 376*3e230dd2SCorentin Chary static int vnc_refresh_server_surface(VncDisplay *vd); 377*3e230dd2SCorentin Chary 378*3e230dd2SCorentin Chary static inline void vnc_set_bit(uint32_t *d, int k) 379*3e230dd2SCorentin Chary { 380*3e230dd2SCorentin Chary d[k >> 5] |= 1 << (k & 0x1f); 381*3e230dd2SCorentin Chary } 382*3e230dd2SCorentin Chary 383*3e230dd2SCorentin Chary static inline void vnc_clear_bit(uint32_t *d, int k) 384*3e230dd2SCorentin Chary { 385*3e230dd2SCorentin Chary d[k >> 5] &= ~(1 << (k & 0x1f)); 386*3e230dd2SCorentin Chary } 387*3e230dd2SCorentin Chary 388*3e230dd2SCorentin Chary static inline void vnc_set_bits(uint32_t *d, int n, int nb_words) 389*3e230dd2SCorentin Chary { 390*3e230dd2SCorentin Chary int j; 391*3e230dd2SCorentin Chary 392*3e230dd2SCorentin Chary j = 0; 393*3e230dd2SCorentin Chary while (n >= 32) { 394*3e230dd2SCorentin Chary d[j++] = -1; 395*3e230dd2SCorentin Chary n -= 32; 396*3e230dd2SCorentin Chary } 397*3e230dd2SCorentin Chary if (n > 0) 398*3e230dd2SCorentin Chary d[j++] = (1 << n) - 1; 399*3e230dd2SCorentin Chary while (j < nb_words) 400*3e230dd2SCorentin Chary d[j++] = 0; 401*3e230dd2SCorentin Chary } 402*3e230dd2SCorentin Chary 403*3e230dd2SCorentin Chary static inline int vnc_get_bit(const uint32_t *d, int k) 404*3e230dd2SCorentin Chary { 405*3e230dd2SCorentin Chary return (d[k >> 5] >> (k & 0x1f)) & 1; 406*3e230dd2SCorentin Chary } 407*3e230dd2SCorentin Chary 408*3e230dd2SCorentin Chary static inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2, 409*3e230dd2SCorentin Chary int nb_words) 410*3e230dd2SCorentin Chary { 411*3e230dd2SCorentin Chary int i; 412*3e230dd2SCorentin Chary for(i = 0; i < nb_words; i++) { 413*3e230dd2SCorentin Chary if ((d1[i] & d2[i]) != 0) 414*3e230dd2SCorentin Chary return 1; 415*3e230dd2SCorentin Chary } 416*3e230dd2SCorentin Chary return 0; 417*3e230dd2SCorentin Chary } 418*3e230dd2SCorentin Chary 419*3e230dd2SCorentin Chary static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h) 420*3e230dd2SCorentin Chary { 421*3e230dd2SCorentin Chary int i; 422*3e230dd2SCorentin Chary VncDisplay *vd = ds->opaque; 423*3e230dd2SCorentin Chary struct VncSurface *s = &vd->guest; 424*3e230dd2SCorentin Chary 425*3e230dd2SCorentin Chary h += y; 426*3e230dd2SCorentin Chary 427*3e230dd2SCorentin Chary /* round x down to ensure the loop only spans one 16-pixel block per, 428*3e230dd2SCorentin Chary iteration. otherwise, if (x % 16) != 0, the last iteration may span 429*3e230dd2SCorentin Chary two 16-pixel blocks but we only mark the first as dirty 430*3e230dd2SCorentin Chary */ 431*3e230dd2SCorentin Chary w += (x % 16); 432*3e230dd2SCorentin Chary x -= (x % 16); 433*3e230dd2SCorentin Chary 434*3e230dd2SCorentin Chary x = MIN(x, s->ds->width); 435*3e230dd2SCorentin Chary y = MIN(y, s->ds->height); 436*3e230dd2SCorentin Chary w = MIN(x + w, s->ds->width) - x; 437*3e230dd2SCorentin Chary h = MIN(h, s->ds->height); 438*3e230dd2SCorentin Chary 439*3e230dd2SCorentin Chary for (; y < h; y++) 440*3e230dd2SCorentin Chary for (i = 0; i < w; i += 16) 441*3e230dd2SCorentin Chary vnc_set_bit(s->dirty[y], (x + i) / 16); 442*3e230dd2SCorentin Chary } 443*3e230dd2SCorentin Chary 444*3e230dd2SCorentin Chary void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h, 445*3e230dd2SCorentin Chary int32_t encoding) 446*3e230dd2SCorentin Chary { 447*3e230dd2SCorentin Chary vnc_write_u16(vs, x); 448*3e230dd2SCorentin Chary vnc_write_u16(vs, y); 449*3e230dd2SCorentin Chary vnc_write_u16(vs, w); 450*3e230dd2SCorentin Chary vnc_write_u16(vs, h); 451*3e230dd2SCorentin Chary 452*3e230dd2SCorentin Chary vnc_write_s32(vs, encoding); 453*3e230dd2SCorentin Chary } 454*3e230dd2SCorentin Chary 455*3e230dd2SCorentin Chary void buffer_reserve(Buffer *buffer, size_t len) 456*3e230dd2SCorentin Chary { 457*3e230dd2SCorentin Chary if ((buffer->capacity - buffer->offset) < len) { 458*3e230dd2SCorentin Chary buffer->capacity += (len + 1024); 459*3e230dd2SCorentin Chary buffer->buffer = qemu_realloc(buffer->buffer, buffer->capacity); 460*3e230dd2SCorentin Chary if (buffer->buffer == NULL) { 461*3e230dd2SCorentin Chary fprintf(stderr, "vnc: out of memory\n"); 462*3e230dd2SCorentin Chary exit(1); 463*3e230dd2SCorentin Chary } 464*3e230dd2SCorentin Chary } 465*3e230dd2SCorentin Chary } 466*3e230dd2SCorentin Chary 467*3e230dd2SCorentin Chary int buffer_empty(Buffer *buffer) 468*3e230dd2SCorentin Chary { 469*3e230dd2SCorentin Chary return buffer->offset == 0; 470*3e230dd2SCorentin Chary } 471*3e230dd2SCorentin Chary 472*3e230dd2SCorentin Chary uint8_t *buffer_end(Buffer *buffer) 473*3e230dd2SCorentin Chary { 474*3e230dd2SCorentin Chary return buffer->buffer + buffer->offset; 475*3e230dd2SCorentin Chary } 476*3e230dd2SCorentin Chary 477*3e230dd2SCorentin Chary void buffer_reset(Buffer *buffer) 478*3e230dd2SCorentin Chary { 479*3e230dd2SCorentin Chary buffer->offset = 0; 480*3e230dd2SCorentin Chary } 481*3e230dd2SCorentin Chary 482*3e230dd2SCorentin Chary void buffer_free(Buffer *buffer) 483*3e230dd2SCorentin Chary { 484*3e230dd2SCorentin Chary qemu_free(buffer->buffer); 485*3e230dd2SCorentin Chary buffer->offset = 0; 486*3e230dd2SCorentin Chary buffer->capacity = 0; 487*3e230dd2SCorentin Chary buffer->buffer = NULL; 488*3e230dd2SCorentin Chary } 489*3e230dd2SCorentin Chary 490*3e230dd2SCorentin Chary void buffer_append(Buffer *buffer, const void *data, size_t len) 491*3e230dd2SCorentin Chary { 492*3e230dd2SCorentin Chary memcpy(buffer->buffer + buffer->offset, data, len); 493*3e230dd2SCorentin Chary buffer->offset += len; 494*3e230dd2SCorentin Chary } 495*3e230dd2SCorentin Chary 496*3e230dd2SCorentin Chary static void vnc_desktop_resize(VncState *vs) 497*3e230dd2SCorentin Chary { 498*3e230dd2SCorentin Chary DisplayState *ds = vs->ds; 499*3e230dd2SCorentin Chary 500*3e230dd2SCorentin Chary if (vs->csock == -1 || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) { 501*3e230dd2SCorentin Chary return; 502*3e230dd2SCorentin Chary } 503*3e230dd2SCorentin Chary if (vs->client_width == ds_get_width(ds) && 504*3e230dd2SCorentin Chary vs->client_height == ds_get_height(ds)) { 505*3e230dd2SCorentin Chary return; 506*3e230dd2SCorentin Chary } 507*3e230dd2SCorentin Chary vs->client_width = ds_get_width(ds); 508*3e230dd2SCorentin Chary vs->client_height = ds_get_height(ds); 509*3e230dd2SCorentin Chary vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); 510*3e230dd2SCorentin Chary vnc_write_u8(vs, 0); 511*3e230dd2SCorentin Chary vnc_write_u16(vs, 1); /* number of rects */ 512*3e230dd2SCorentin Chary vnc_framebuffer_update(vs, 0, 0, vs->client_width, vs->client_height, 513*3e230dd2SCorentin Chary VNC_ENCODING_DESKTOPRESIZE); 514*3e230dd2SCorentin Chary vnc_flush(vs); 515*3e230dd2SCorentin Chary } 516*3e230dd2SCorentin Chary 517*3e230dd2SCorentin Chary static void vnc_dpy_resize(DisplayState *ds) 518*3e230dd2SCorentin Chary { 519*3e230dd2SCorentin Chary VncDisplay *vd = ds->opaque; 520*3e230dd2SCorentin Chary VncState *vs; 521*3e230dd2SCorentin Chary 522*3e230dd2SCorentin Chary /* server surface */ 523*3e230dd2SCorentin Chary if (!vd->server) 524*3e230dd2SCorentin Chary vd->server = qemu_mallocz(sizeof(*vd->server)); 525*3e230dd2SCorentin Chary if (vd->server->data) 526*3e230dd2SCorentin Chary qemu_free(vd->server->data); 527*3e230dd2SCorentin Chary *(vd->server) = *(ds->surface); 528*3e230dd2SCorentin Chary vd->server->data = qemu_mallocz(vd->server->linesize * 529*3e230dd2SCorentin Chary vd->server->height); 530*3e230dd2SCorentin Chary 531*3e230dd2SCorentin Chary /* guest surface */ 532*3e230dd2SCorentin Chary if (!vd->guest.ds) 533*3e230dd2SCorentin Chary vd->guest.ds = qemu_mallocz(sizeof(*vd->guest.ds)); 534*3e230dd2SCorentin Chary if (ds_get_bytes_per_pixel(ds) != vd->guest.ds->pf.bytes_per_pixel) 535*3e230dd2SCorentin Chary console_color_init(ds); 536*3e230dd2SCorentin Chary *(vd->guest.ds) = *(ds->surface); 537*3e230dd2SCorentin Chary memset(vd->guest.dirty, 0xFF, sizeof(vd->guest.dirty)); 538*3e230dd2SCorentin Chary 539*3e230dd2SCorentin Chary QTAILQ_FOREACH(vs, &vd->clients, next) { 540*3e230dd2SCorentin Chary vnc_colordepth(vs); 541*3e230dd2SCorentin Chary vnc_desktop_resize(vs); 542*3e230dd2SCorentin Chary if (vs->vd->cursor) { 543*3e230dd2SCorentin Chary vnc_cursor_define(vs); 544*3e230dd2SCorentin Chary } 545*3e230dd2SCorentin Chary memset(vs->dirty, 0xFF, sizeof(vs->dirty)); 546*3e230dd2SCorentin Chary } 547*3e230dd2SCorentin Chary } 548*3e230dd2SCorentin Chary 549*3e230dd2SCorentin Chary /* fastest code */ 550*3e230dd2SCorentin Chary static void vnc_write_pixels_copy(VncState *vs, struct PixelFormat *pf, 551*3e230dd2SCorentin Chary void *pixels, int size) 552*3e230dd2SCorentin Chary { 553*3e230dd2SCorentin Chary vnc_write(vs, pixels, size); 554*3e230dd2SCorentin Chary } 555*3e230dd2SCorentin Chary 556*3e230dd2SCorentin Chary /* slowest but generic code. */ 557*3e230dd2SCorentin Chary void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v) 558*3e230dd2SCorentin Chary { 559*3e230dd2SCorentin Chary uint8_t r, g, b; 560*3e230dd2SCorentin Chary VncDisplay *vd = vs->vd; 561*3e230dd2SCorentin Chary 562*3e230dd2SCorentin Chary r = ((((v & vd->server->pf.rmask) >> vd->server->pf.rshift) << vs->clientds.pf.rbits) >> 563*3e230dd2SCorentin Chary vd->server->pf.rbits); 564*3e230dd2SCorentin Chary g = ((((v & vd->server->pf.gmask) >> vd->server->pf.gshift) << vs->clientds.pf.gbits) >> 565*3e230dd2SCorentin Chary vd->server->pf.gbits); 566*3e230dd2SCorentin Chary b = ((((v & vd->server->pf.bmask) >> vd->server->pf.bshift) << vs->clientds.pf.bbits) >> 567*3e230dd2SCorentin Chary vd->server->pf.bbits); 568*3e230dd2SCorentin Chary v = (r << vs->clientds.pf.rshift) | 569*3e230dd2SCorentin Chary (g << vs->clientds.pf.gshift) | 570*3e230dd2SCorentin Chary (b << vs->clientds.pf.bshift); 571*3e230dd2SCorentin Chary switch(vs->clientds.pf.bytes_per_pixel) { 572*3e230dd2SCorentin Chary case 1: 573*3e230dd2SCorentin Chary buf[0] = v; 574*3e230dd2SCorentin Chary break; 575*3e230dd2SCorentin Chary case 2: 576*3e230dd2SCorentin Chary if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) { 577*3e230dd2SCorentin Chary buf[0] = v >> 8; 578*3e230dd2SCorentin Chary buf[1] = v; 579*3e230dd2SCorentin Chary } else { 580*3e230dd2SCorentin Chary buf[1] = v >> 8; 581*3e230dd2SCorentin Chary buf[0] = v; 582*3e230dd2SCorentin Chary } 583*3e230dd2SCorentin Chary break; 584*3e230dd2SCorentin Chary default: 585*3e230dd2SCorentin Chary case 4: 586*3e230dd2SCorentin Chary if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) { 587*3e230dd2SCorentin Chary buf[0] = v >> 24; 588*3e230dd2SCorentin Chary buf[1] = v >> 16; 589*3e230dd2SCorentin Chary buf[2] = v >> 8; 590*3e230dd2SCorentin Chary buf[3] = v; 591*3e230dd2SCorentin Chary } else { 592*3e230dd2SCorentin Chary buf[3] = v >> 24; 593*3e230dd2SCorentin Chary buf[2] = v >> 16; 594*3e230dd2SCorentin Chary buf[1] = v >> 8; 595*3e230dd2SCorentin Chary buf[0] = v; 596*3e230dd2SCorentin Chary } 597*3e230dd2SCorentin Chary break; 598*3e230dd2SCorentin Chary } 599*3e230dd2SCorentin Chary } 600*3e230dd2SCorentin Chary 601*3e230dd2SCorentin Chary static void vnc_write_pixels_generic(VncState *vs, struct PixelFormat *pf, 602*3e230dd2SCorentin Chary void *pixels1, int size) 603*3e230dd2SCorentin Chary { 604*3e230dd2SCorentin Chary uint8_t buf[4]; 605*3e230dd2SCorentin Chary 606*3e230dd2SCorentin Chary if (pf->bytes_per_pixel == 4) { 607*3e230dd2SCorentin Chary uint32_t *pixels = pixels1; 608*3e230dd2SCorentin Chary int n, i; 609*3e230dd2SCorentin Chary n = size >> 2; 610*3e230dd2SCorentin Chary for(i = 0; i < n; i++) { 611*3e230dd2SCorentin Chary vnc_convert_pixel(vs, buf, pixels[i]); 612*3e230dd2SCorentin Chary vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel); 613*3e230dd2SCorentin Chary } 614*3e230dd2SCorentin Chary } else if (pf->bytes_per_pixel == 2) { 615*3e230dd2SCorentin Chary uint16_t *pixels = pixels1; 616*3e230dd2SCorentin Chary int n, i; 617*3e230dd2SCorentin Chary n = size >> 1; 618*3e230dd2SCorentin Chary for(i = 0; i < n; i++) { 619*3e230dd2SCorentin Chary vnc_convert_pixel(vs, buf, pixels[i]); 620*3e230dd2SCorentin Chary vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel); 621*3e230dd2SCorentin Chary } 622*3e230dd2SCorentin Chary } else if (pf->bytes_per_pixel == 1) { 623*3e230dd2SCorentin Chary uint8_t *pixels = pixels1; 624*3e230dd2SCorentin Chary int n, i; 625*3e230dd2SCorentin Chary n = size; 626*3e230dd2SCorentin Chary for(i = 0; i < n; i++) { 627*3e230dd2SCorentin Chary vnc_convert_pixel(vs, buf, pixels[i]); 628*3e230dd2SCorentin Chary vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel); 629*3e230dd2SCorentin Chary } 630*3e230dd2SCorentin Chary } else { 631*3e230dd2SCorentin Chary fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n"); 632*3e230dd2SCorentin Chary } 633*3e230dd2SCorentin Chary } 634*3e230dd2SCorentin Chary 635*3e230dd2SCorentin Chary int vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) 636*3e230dd2SCorentin Chary { 637*3e230dd2SCorentin Chary int i; 638*3e230dd2SCorentin Chary uint8_t *row; 639*3e230dd2SCorentin Chary VncDisplay *vd = vs->vd; 640*3e230dd2SCorentin Chary 641*3e230dd2SCorentin Chary row = vd->server->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds); 642*3e230dd2SCorentin Chary for (i = 0; i < h; i++) { 643*3e230dd2SCorentin Chary vs->write_pixels(vs, &vd->server->pf, row, w * ds_get_bytes_per_pixel(vs->ds)); 644*3e230dd2SCorentin Chary row += ds_get_linesize(vs->ds); 645*3e230dd2SCorentin Chary } 646*3e230dd2SCorentin Chary return 1; 647*3e230dd2SCorentin Chary } 648*3e230dd2SCorentin Chary 649*3e230dd2SCorentin Chary static int send_framebuffer_update(VncState *vs, int x, int y, int w, int h) 650*3e230dd2SCorentin Chary { 651*3e230dd2SCorentin Chary int n = 0; 652*3e230dd2SCorentin Chary 653*3e230dd2SCorentin Chary switch(vs->vnc_encoding) { 654*3e230dd2SCorentin Chary case VNC_ENCODING_ZLIB: 655*3e230dd2SCorentin Chary n = vnc_zlib_send_framebuffer_update(vs, x, y, w, h); 656*3e230dd2SCorentin Chary break; 657*3e230dd2SCorentin Chary case VNC_ENCODING_HEXTILE: 658*3e230dd2SCorentin Chary vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE); 659*3e230dd2SCorentin Chary n = vnc_hextile_send_framebuffer_update(vs, x, y, w, h); 660*3e230dd2SCorentin Chary break; 661*3e230dd2SCorentin Chary case VNC_ENCODING_TIGHT: 662*3e230dd2SCorentin Chary n = vnc_tight_send_framebuffer_update(vs, x, y, w, h); 663*3e230dd2SCorentin Chary break; 664*3e230dd2SCorentin Chary default: 665*3e230dd2SCorentin Chary vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW); 666*3e230dd2SCorentin Chary n = vnc_raw_send_framebuffer_update(vs, x, y, w, h); 667*3e230dd2SCorentin Chary break; 668*3e230dd2SCorentin Chary } 669*3e230dd2SCorentin Chary return n; 670*3e230dd2SCorentin Chary } 671*3e230dd2SCorentin Chary 672*3e230dd2SCorentin Chary static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h) 673*3e230dd2SCorentin Chary { 674*3e230dd2SCorentin Chary /* send bitblit op to the vnc client */ 675*3e230dd2SCorentin Chary vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); 676*3e230dd2SCorentin Chary vnc_write_u8(vs, 0); 677*3e230dd2SCorentin Chary vnc_write_u16(vs, 1); /* number of rects */ 678*3e230dd2SCorentin Chary vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT); 679*3e230dd2SCorentin Chary vnc_write_u16(vs, src_x); 680*3e230dd2SCorentin Chary vnc_write_u16(vs, src_y); 681*3e230dd2SCorentin Chary vnc_flush(vs); 682*3e230dd2SCorentin Chary } 683*3e230dd2SCorentin Chary 684*3e230dd2SCorentin Chary static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h) 685*3e230dd2SCorentin Chary { 686*3e230dd2SCorentin Chary VncDisplay *vd = ds->opaque; 687*3e230dd2SCorentin Chary VncState *vs, *vn; 688*3e230dd2SCorentin Chary uint8_t *src_row; 689*3e230dd2SCorentin Chary uint8_t *dst_row; 690*3e230dd2SCorentin Chary int i,x,y,pitch,depth,inc,w_lim,s; 691*3e230dd2SCorentin Chary int cmp_bytes; 692*3e230dd2SCorentin Chary 693*3e230dd2SCorentin Chary vnc_refresh_server_surface(vd); 694*3e230dd2SCorentin Chary QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) { 695*3e230dd2SCorentin Chary if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) { 696*3e230dd2SCorentin Chary vs->force_update = 1; 697*3e230dd2SCorentin Chary vnc_update_client(vs, 1); 698*3e230dd2SCorentin Chary /* vs might be free()ed here */ 699*3e230dd2SCorentin Chary } 700*3e230dd2SCorentin Chary } 701*3e230dd2SCorentin Chary 702*3e230dd2SCorentin Chary /* do bitblit op on the local surface too */ 703*3e230dd2SCorentin Chary pitch = ds_get_linesize(vd->ds); 704*3e230dd2SCorentin Chary depth = ds_get_bytes_per_pixel(vd->ds); 705*3e230dd2SCorentin Chary src_row = vd->server->data + pitch * src_y + depth * src_x; 706*3e230dd2SCorentin Chary dst_row = vd->server->data + pitch * dst_y + depth * dst_x; 707*3e230dd2SCorentin Chary y = dst_y; 708*3e230dd2SCorentin Chary inc = 1; 709*3e230dd2SCorentin Chary if (dst_y > src_y) { 710*3e230dd2SCorentin Chary /* copy backwards */ 711*3e230dd2SCorentin Chary src_row += pitch * (h-1); 712*3e230dd2SCorentin Chary dst_row += pitch * (h-1); 713*3e230dd2SCorentin Chary pitch = -pitch; 714*3e230dd2SCorentin Chary y = dst_y + h - 1; 715*3e230dd2SCorentin Chary inc = -1; 716*3e230dd2SCorentin Chary } 717*3e230dd2SCorentin Chary w_lim = w - (16 - (dst_x % 16)); 718*3e230dd2SCorentin Chary if (w_lim < 0) 719*3e230dd2SCorentin Chary w_lim = w; 720*3e230dd2SCorentin Chary else 721*3e230dd2SCorentin Chary w_lim = w - (w_lim % 16); 722*3e230dd2SCorentin Chary for (i = 0; i < h; i++) { 723*3e230dd2SCorentin Chary for (x = 0; x <= w_lim; 724*3e230dd2SCorentin Chary x += s, src_row += cmp_bytes, dst_row += cmp_bytes) { 725*3e230dd2SCorentin Chary if (x == w_lim) { 726*3e230dd2SCorentin Chary if ((s = w - w_lim) == 0) 727*3e230dd2SCorentin Chary break; 728*3e230dd2SCorentin Chary } else if (!x) { 729*3e230dd2SCorentin Chary s = (16 - (dst_x % 16)); 730*3e230dd2SCorentin Chary s = MIN(s, w_lim); 731*3e230dd2SCorentin Chary } else { 732*3e230dd2SCorentin Chary s = 16; 733*3e230dd2SCorentin Chary } 734*3e230dd2SCorentin Chary cmp_bytes = s * depth; 735*3e230dd2SCorentin Chary if (memcmp(src_row, dst_row, cmp_bytes) == 0) 736*3e230dd2SCorentin Chary continue; 737*3e230dd2SCorentin Chary memmove(dst_row, src_row, cmp_bytes); 738*3e230dd2SCorentin Chary QTAILQ_FOREACH(vs, &vd->clients, next) { 739*3e230dd2SCorentin Chary if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) { 740*3e230dd2SCorentin Chary vnc_set_bit(vs->dirty[y], ((x + dst_x) / 16)); 741*3e230dd2SCorentin Chary } 742*3e230dd2SCorentin Chary } 743*3e230dd2SCorentin Chary } 744*3e230dd2SCorentin Chary src_row += pitch - w * depth; 745*3e230dd2SCorentin Chary dst_row += pitch - w * depth; 746*3e230dd2SCorentin Chary y += inc; 747*3e230dd2SCorentin Chary } 748*3e230dd2SCorentin Chary 749*3e230dd2SCorentin Chary QTAILQ_FOREACH(vs, &vd->clients, next) { 750*3e230dd2SCorentin Chary if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) { 751*3e230dd2SCorentin Chary vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h); 752*3e230dd2SCorentin Chary } 753*3e230dd2SCorentin Chary } 754*3e230dd2SCorentin Chary } 755*3e230dd2SCorentin Chary 756*3e230dd2SCorentin Chary static void vnc_mouse_set(int x, int y, int visible) 757*3e230dd2SCorentin Chary { 758*3e230dd2SCorentin Chary /* can we ask the client(s) to move the pointer ??? */ 759*3e230dd2SCorentin Chary } 760*3e230dd2SCorentin Chary 761*3e230dd2SCorentin Chary static int vnc_cursor_define(VncState *vs) 762*3e230dd2SCorentin Chary { 763*3e230dd2SCorentin Chary QEMUCursor *c = vs->vd->cursor; 764*3e230dd2SCorentin Chary PixelFormat pf = qemu_default_pixelformat(32); 765*3e230dd2SCorentin Chary int isize; 766*3e230dd2SCorentin Chary 767*3e230dd2SCorentin Chary if (vnc_has_feature(vs, VNC_FEATURE_RICH_CURSOR)) { 768*3e230dd2SCorentin Chary vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); 769*3e230dd2SCorentin Chary vnc_write_u8(vs, 0); /* padding */ 770*3e230dd2SCorentin Chary vnc_write_u16(vs, 1); /* # of rects */ 771*3e230dd2SCorentin Chary vnc_framebuffer_update(vs, c->hot_x, c->hot_y, c->width, c->height, 772*3e230dd2SCorentin Chary VNC_ENCODING_RICH_CURSOR); 773*3e230dd2SCorentin Chary isize = c->width * c->height * vs->clientds.pf.bytes_per_pixel; 774*3e230dd2SCorentin Chary vnc_write_pixels_generic(vs, &pf, c->data, isize); 775*3e230dd2SCorentin Chary vnc_write(vs, vs->vd->cursor_mask, vs->vd->cursor_msize); 776*3e230dd2SCorentin Chary return 0; 777*3e230dd2SCorentin Chary } 778*3e230dd2SCorentin Chary return -1; 779*3e230dd2SCorentin Chary } 780*3e230dd2SCorentin Chary 781*3e230dd2SCorentin Chary static void vnc_dpy_cursor_define(QEMUCursor *c) 782*3e230dd2SCorentin Chary { 783*3e230dd2SCorentin Chary VncDisplay *vd = vnc_display; 784*3e230dd2SCorentin Chary VncState *vs; 785*3e230dd2SCorentin Chary 786*3e230dd2SCorentin Chary cursor_put(vd->cursor); 787*3e230dd2SCorentin Chary qemu_free(vd->cursor_mask); 788*3e230dd2SCorentin Chary 789*3e230dd2SCorentin Chary vd->cursor = c; 790*3e230dd2SCorentin Chary cursor_get(vd->cursor); 791*3e230dd2SCorentin Chary vd->cursor_msize = cursor_get_mono_bpl(c) * c->height; 792*3e230dd2SCorentin Chary vd->cursor_mask = qemu_mallocz(vd->cursor_msize); 793*3e230dd2SCorentin Chary cursor_get_mono_mask(c, 0, vd->cursor_mask); 794*3e230dd2SCorentin Chary 795*3e230dd2SCorentin Chary QTAILQ_FOREACH(vs, &vd->clients, next) { 796*3e230dd2SCorentin Chary vnc_cursor_define(vs); 797*3e230dd2SCorentin Chary } 798*3e230dd2SCorentin Chary } 799*3e230dd2SCorentin Chary 800*3e230dd2SCorentin Chary static int find_and_clear_dirty_height(struct VncState *vs, 801*3e230dd2SCorentin Chary int y, int last_x, int x) 802*3e230dd2SCorentin Chary { 803*3e230dd2SCorentin Chary int h; 804*3e230dd2SCorentin Chary VncDisplay *vd = vs->vd; 805*3e230dd2SCorentin Chary 806*3e230dd2SCorentin Chary for (h = 1; h < (vd->server->height - y); h++) { 807*3e230dd2SCorentin Chary int tmp_x; 808*3e230dd2SCorentin Chary if (!vnc_get_bit(vs->dirty[y + h], last_x)) 809*3e230dd2SCorentin Chary break; 810*3e230dd2SCorentin Chary for (tmp_x = last_x; tmp_x < x; tmp_x++) 811*3e230dd2SCorentin Chary vnc_clear_bit(vs->dirty[y + h], tmp_x); 812*3e230dd2SCorentin Chary } 813*3e230dd2SCorentin Chary 814*3e230dd2SCorentin Chary return h; 815*3e230dd2SCorentin Chary } 816*3e230dd2SCorentin Chary 817*3e230dd2SCorentin Chary static int vnc_update_client(VncState *vs, int has_dirty) 818*3e230dd2SCorentin Chary { 819*3e230dd2SCorentin Chary if (vs->need_update && vs->csock != -1) { 820*3e230dd2SCorentin Chary VncDisplay *vd = vs->vd; 821*3e230dd2SCorentin Chary int y; 822*3e230dd2SCorentin Chary int n_rectangles; 823*3e230dd2SCorentin Chary int saved_offset; 824*3e230dd2SCorentin Chary int width, height; 825*3e230dd2SCorentin Chary int n; 826*3e230dd2SCorentin Chary 827*3e230dd2SCorentin Chary if (vs->output.offset && !vs->audio_cap && !vs->force_update) 828*3e230dd2SCorentin Chary /* kernel send buffers are full -> drop frames to throttle */ 829*3e230dd2SCorentin Chary return 0; 830*3e230dd2SCorentin Chary 831*3e230dd2SCorentin Chary if (!has_dirty && !vs->audio_cap && !vs->force_update) 832*3e230dd2SCorentin Chary return 0; 833*3e230dd2SCorentin Chary 834*3e230dd2SCorentin Chary /* 835*3e230dd2SCorentin Chary * Send screen updates to the vnc client using the server 836*3e230dd2SCorentin Chary * surface and server dirty map. guest surface updates 837*3e230dd2SCorentin Chary * happening in parallel don't disturb us, the next pass will 838*3e230dd2SCorentin Chary * send them to the client. 839*3e230dd2SCorentin Chary */ 840*3e230dd2SCorentin Chary n_rectangles = 0; 841*3e230dd2SCorentin Chary vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); 842*3e230dd2SCorentin Chary vnc_write_u8(vs, 0); 843*3e230dd2SCorentin Chary saved_offset = vs->output.offset; 844*3e230dd2SCorentin Chary vnc_write_u16(vs, 0); 845*3e230dd2SCorentin Chary 846*3e230dd2SCorentin Chary width = MIN(vd->server->width, vs->client_width); 847*3e230dd2SCorentin Chary height = MIN(vd->server->height, vs->client_height); 848*3e230dd2SCorentin Chary 849*3e230dd2SCorentin Chary for (y = 0; y < height; y++) { 850*3e230dd2SCorentin Chary int x; 851*3e230dd2SCorentin Chary int last_x = -1; 852*3e230dd2SCorentin Chary for (x = 0; x < width / 16; x++) { 853*3e230dd2SCorentin Chary if (vnc_get_bit(vs->dirty[y], x)) { 854*3e230dd2SCorentin Chary if (last_x == -1) { 855*3e230dd2SCorentin Chary last_x = x; 856*3e230dd2SCorentin Chary } 857*3e230dd2SCorentin Chary vnc_clear_bit(vs->dirty[y], x); 858*3e230dd2SCorentin Chary } else { 859*3e230dd2SCorentin Chary if (last_x != -1) { 860*3e230dd2SCorentin Chary int h = find_and_clear_dirty_height(vs, y, last_x, x); 861*3e230dd2SCorentin Chary n = send_framebuffer_update(vs, last_x * 16, y, 862*3e230dd2SCorentin Chary (x - last_x) * 16, h); 863*3e230dd2SCorentin Chary n_rectangles += n; 864*3e230dd2SCorentin Chary } 865*3e230dd2SCorentin Chary last_x = -1; 866*3e230dd2SCorentin Chary } 867*3e230dd2SCorentin Chary } 868*3e230dd2SCorentin Chary if (last_x != -1) { 869*3e230dd2SCorentin Chary int h = find_and_clear_dirty_height(vs, y, last_x, x); 870*3e230dd2SCorentin Chary n = send_framebuffer_update(vs, last_x * 16, y, 871*3e230dd2SCorentin Chary (x - last_x) * 16, h); 872*3e230dd2SCorentin Chary n_rectangles += n; 873*3e230dd2SCorentin Chary } 874*3e230dd2SCorentin Chary } 875*3e230dd2SCorentin Chary vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF; 876*3e230dd2SCorentin Chary vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF; 877*3e230dd2SCorentin Chary vnc_flush(vs); 878*3e230dd2SCorentin Chary vs->force_update = 0; 879*3e230dd2SCorentin Chary return n_rectangles; 880*3e230dd2SCorentin Chary } 881*3e230dd2SCorentin Chary 882*3e230dd2SCorentin Chary if (vs->csock == -1) 883*3e230dd2SCorentin Chary vnc_disconnect_finish(vs); 884*3e230dd2SCorentin Chary 885*3e230dd2SCorentin Chary return 0; 886*3e230dd2SCorentin Chary } 887*3e230dd2SCorentin Chary 888*3e230dd2SCorentin Chary /* audio */ 889*3e230dd2SCorentin Chary static void audio_capture_notify(void *opaque, audcnotification_e cmd) 890*3e230dd2SCorentin Chary { 891*3e230dd2SCorentin Chary VncState *vs = opaque; 892*3e230dd2SCorentin Chary 893*3e230dd2SCorentin Chary switch (cmd) { 894*3e230dd2SCorentin Chary case AUD_CNOTIFY_DISABLE: 895*3e230dd2SCorentin Chary vnc_write_u8(vs, VNC_MSG_SERVER_QEMU); 896*3e230dd2SCorentin Chary vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO); 897*3e230dd2SCorentin Chary vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_END); 898*3e230dd2SCorentin Chary vnc_flush(vs); 899*3e230dd2SCorentin Chary break; 900*3e230dd2SCorentin Chary 901*3e230dd2SCorentin Chary case AUD_CNOTIFY_ENABLE: 902*3e230dd2SCorentin Chary vnc_write_u8(vs, VNC_MSG_SERVER_QEMU); 903*3e230dd2SCorentin Chary vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO); 904*3e230dd2SCorentin Chary vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_BEGIN); 905*3e230dd2SCorentin Chary vnc_flush(vs); 906*3e230dd2SCorentin Chary break; 907*3e230dd2SCorentin Chary } 908*3e230dd2SCorentin Chary } 909*3e230dd2SCorentin Chary 910*3e230dd2SCorentin Chary static void audio_capture_destroy(void *opaque) 911*3e230dd2SCorentin Chary { 912*3e230dd2SCorentin Chary } 913*3e230dd2SCorentin Chary 914*3e230dd2SCorentin Chary static void audio_capture(void *opaque, void *buf, int size) 915*3e230dd2SCorentin Chary { 916*3e230dd2SCorentin Chary VncState *vs = opaque; 917*3e230dd2SCorentin Chary 918*3e230dd2SCorentin Chary vnc_write_u8(vs, VNC_MSG_SERVER_QEMU); 919*3e230dd2SCorentin Chary vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO); 920*3e230dd2SCorentin Chary vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_DATA); 921*3e230dd2SCorentin Chary vnc_write_u32(vs, size); 922*3e230dd2SCorentin Chary vnc_write(vs, buf, size); 923*3e230dd2SCorentin Chary vnc_flush(vs); 924*3e230dd2SCorentin Chary } 925*3e230dd2SCorentin Chary 926*3e230dd2SCorentin Chary static void audio_add(VncState *vs) 927*3e230dd2SCorentin Chary { 928*3e230dd2SCorentin Chary struct audio_capture_ops ops; 929*3e230dd2SCorentin Chary 930*3e230dd2SCorentin Chary if (vs->audio_cap) { 931*3e230dd2SCorentin Chary monitor_printf(default_mon, "audio already running\n"); 932*3e230dd2SCorentin Chary return; 933*3e230dd2SCorentin Chary } 934*3e230dd2SCorentin Chary 935*3e230dd2SCorentin Chary ops.notify = audio_capture_notify; 936*3e230dd2SCorentin Chary ops.destroy = audio_capture_destroy; 937*3e230dd2SCorentin Chary ops.capture = audio_capture; 938*3e230dd2SCorentin Chary 939*3e230dd2SCorentin Chary vs->audio_cap = AUD_add_capture(&vs->as, &ops, vs); 940*3e230dd2SCorentin Chary if (!vs->audio_cap) { 941*3e230dd2SCorentin Chary monitor_printf(default_mon, "Failed to add audio capture\n"); 942*3e230dd2SCorentin Chary } 943*3e230dd2SCorentin Chary } 944*3e230dd2SCorentin Chary 945*3e230dd2SCorentin Chary static void audio_del(VncState *vs) 946*3e230dd2SCorentin Chary { 947*3e230dd2SCorentin Chary if (vs->audio_cap) { 948*3e230dd2SCorentin Chary AUD_del_capture(vs->audio_cap, vs); 949*3e230dd2SCorentin Chary vs->audio_cap = NULL; 950*3e230dd2SCorentin Chary } 951*3e230dd2SCorentin Chary } 952*3e230dd2SCorentin Chary 953*3e230dd2SCorentin Chary static void vnc_disconnect_start(VncState *vs) 954*3e230dd2SCorentin Chary { 955*3e230dd2SCorentin Chary if (vs->csock == -1) 956*3e230dd2SCorentin Chary return; 957*3e230dd2SCorentin Chary qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL); 958*3e230dd2SCorentin Chary closesocket(vs->csock); 959*3e230dd2SCorentin Chary vs->csock = -1; 960*3e230dd2SCorentin Chary } 961*3e230dd2SCorentin Chary 962*3e230dd2SCorentin Chary static void vnc_disconnect_finish(VncState *vs) 963*3e230dd2SCorentin Chary { 964*3e230dd2SCorentin Chary vnc_qmp_event(vs, QEVENT_VNC_DISCONNECTED); 965*3e230dd2SCorentin Chary 966*3e230dd2SCorentin Chary buffer_free(&vs->input); 967*3e230dd2SCorentin Chary buffer_free(&vs->output); 968*3e230dd2SCorentin Chary 969*3e230dd2SCorentin Chary qobject_decref(vs->info); 970*3e230dd2SCorentin Chary 971*3e230dd2SCorentin Chary vnc_zlib_clear(vs); 972*3e230dd2SCorentin Chary vnc_tight_clear(vs); 973*3e230dd2SCorentin Chary 974*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 975*3e230dd2SCorentin Chary vnc_tls_client_cleanup(vs); 976*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_TLS */ 977*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL 978*3e230dd2SCorentin Chary vnc_sasl_client_cleanup(vs); 979*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_SASL */ 980*3e230dd2SCorentin Chary audio_del(vs); 981*3e230dd2SCorentin Chary 982*3e230dd2SCorentin Chary QTAILQ_REMOVE(&vs->vd->clients, vs, next); 983*3e230dd2SCorentin Chary 984*3e230dd2SCorentin Chary if (QTAILQ_EMPTY(&vs->vd->clients)) { 985*3e230dd2SCorentin Chary dcl->idle = 1; 986*3e230dd2SCorentin Chary } 987*3e230dd2SCorentin Chary 988*3e230dd2SCorentin Chary qemu_remove_mouse_mode_change_notifier(&vs->mouse_mode_notifier); 989*3e230dd2SCorentin Chary vnc_remove_timer(vs->vd); 990*3e230dd2SCorentin Chary if (vs->vd->lock_key_sync) 991*3e230dd2SCorentin Chary qemu_remove_led_event_handler(vs->led); 992*3e230dd2SCorentin Chary qemu_free(vs); 993*3e230dd2SCorentin Chary } 994*3e230dd2SCorentin Chary 995*3e230dd2SCorentin Chary int vnc_client_io_error(VncState *vs, int ret, int last_errno) 996*3e230dd2SCorentin Chary { 997*3e230dd2SCorentin Chary if (ret == 0 || ret == -1) { 998*3e230dd2SCorentin Chary if (ret == -1) { 999*3e230dd2SCorentin Chary switch (last_errno) { 1000*3e230dd2SCorentin Chary case EINTR: 1001*3e230dd2SCorentin Chary case EAGAIN: 1002*3e230dd2SCorentin Chary #ifdef _WIN32 1003*3e230dd2SCorentin Chary case WSAEWOULDBLOCK: 1004*3e230dd2SCorentin Chary #endif 1005*3e230dd2SCorentin Chary return 0; 1006*3e230dd2SCorentin Chary default: 1007*3e230dd2SCorentin Chary break; 1008*3e230dd2SCorentin Chary } 1009*3e230dd2SCorentin Chary } 1010*3e230dd2SCorentin Chary 1011*3e230dd2SCorentin Chary VNC_DEBUG("Closing down client sock: ret %d, errno %d\n", 1012*3e230dd2SCorentin Chary ret, ret < 0 ? last_errno : 0); 1013*3e230dd2SCorentin Chary vnc_disconnect_start(vs); 1014*3e230dd2SCorentin Chary 1015*3e230dd2SCorentin Chary return 0; 1016*3e230dd2SCorentin Chary } 1017*3e230dd2SCorentin Chary return ret; 1018*3e230dd2SCorentin Chary } 1019*3e230dd2SCorentin Chary 1020*3e230dd2SCorentin Chary 1021*3e230dd2SCorentin Chary void vnc_client_error(VncState *vs) 1022*3e230dd2SCorentin Chary { 1023*3e230dd2SCorentin Chary VNC_DEBUG("Closing down client sock: protocol error\n"); 1024*3e230dd2SCorentin Chary vnc_disconnect_start(vs); 1025*3e230dd2SCorentin Chary } 1026*3e230dd2SCorentin Chary 1027*3e230dd2SCorentin Chary 1028*3e230dd2SCorentin Chary /* 1029*3e230dd2SCorentin Chary * Called to write a chunk of data to the client socket. The data may 1030*3e230dd2SCorentin Chary * be the raw data, or may have already been encoded by SASL. 1031*3e230dd2SCorentin Chary * The data will be written either straight onto the socket, or 1032*3e230dd2SCorentin Chary * written via the GNUTLS wrappers, if TLS/SSL encryption is enabled 1033*3e230dd2SCorentin Chary * 1034*3e230dd2SCorentin Chary * NB, it is theoretically possible to have 2 layers of encryption, 1035*3e230dd2SCorentin Chary * both SASL, and this TLS layer. It is highly unlikely in practice 1036*3e230dd2SCorentin Chary * though, since SASL encryption will typically be a no-op if TLS 1037*3e230dd2SCorentin Chary * is active 1038*3e230dd2SCorentin Chary * 1039*3e230dd2SCorentin Chary * Returns the number of bytes written, which may be less than 1040*3e230dd2SCorentin Chary * the requested 'datalen' if the socket would block. Returns 1041*3e230dd2SCorentin Chary * -1 on error, and disconnects the client socket. 1042*3e230dd2SCorentin Chary */ 1043*3e230dd2SCorentin Chary long vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen) 1044*3e230dd2SCorentin Chary { 1045*3e230dd2SCorentin Chary long ret; 1046*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 1047*3e230dd2SCorentin Chary if (vs->tls.session) { 1048*3e230dd2SCorentin Chary ret = gnutls_write(vs->tls.session, data, datalen); 1049*3e230dd2SCorentin Chary if (ret < 0) { 1050*3e230dd2SCorentin Chary if (ret == GNUTLS_E_AGAIN) 1051*3e230dd2SCorentin Chary errno = EAGAIN; 1052*3e230dd2SCorentin Chary else 1053*3e230dd2SCorentin Chary errno = EIO; 1054*3e230dd2SCorentin Chary ret = -1; 1055*3e230dd2SCorentin Chary } 1056*3e230dd2SCorentin Chary } else 1057*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_TLS */ 1058*3e230dd2SCorentin Chary ret = send(vs->csock, (const void *)data, datalen, 0); 1059*3e230dd2SCorentin Chary VNC_DEBUG("Wrote wire %p %zd -> %ld\n", data, datalen, ret); 1060*3e230dd2SCorentin Chary return vnc_client_io_error(vs, ret, socket_error()); 1061*3e230dd2SCorentin Chary } 1062*3e230dd2SCorentin Chary 1063*3e230dd2SCorentin Chary 1064*3e230dd2SCorentin Chary /* 1065*3e230dd2SCorentin Chary * Called to write buffered data to the client socket, when not 1066*3e230dd2SCorentin Chary * using any SASL SSF encryption layers. Will write as much data 1067*3e230dd2SCorentin Chary * as possible without blocking. If all buffered data is written, 1068*3e230dd2SCorentin Chary * will switch the FD poll() handler back to read monitoring. 1069*3e230dd2SCorentin Chary * 1070*3e230dd2SCorentin Chary * Returns the number of bytes written, which may be less than 1071*3e230dd2SCorentin Chary * the buffered output data if the socket would block. Returns 1072*3e230dd2SCorentin Chary * -1 on error, and disconnects the client socket. 1073*3e230dd2SCorentin Chary */ 1074*3e230dd2SCorentin Chary static long vnc_client_write_plain(VncState *vs) 1075*3e230dd2SCorentin Chary { 1076*3e230dd2SCorentin Chary long ret; 1077*3e230dd2SCorentin Chary 1078*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL 1079*3e230dd2SCorentin Chary VNC_DEBUG("Write Plain: Pending output %p size %zd offset %zd. Wait SSF %d\n", 1080*3e230dd2SCorentin Chary vs->output.buffer, vs->output.capacity, vs->output.offset, 1081*3e230dd2SCorentin Chary vs->sasl.waitWriteSSF); 1082*3e230dd2SCorentin Chary 1083*3e230dd2SCorentin Chary if (vs->sasl.conn && 1084*3e230dd2SCorentin Chary vs->sasl.runSSF && 1085*3e230dd2SCorentin Chary vs->sasl.waitWriteSSF) { 1086*3e230dd2SCorentin Chary ret = vnc_client_write_buf(vs, vs->output.buffer, vs->sasl.waitWriteSSF); 1087*3e230dd2SCorentin Chary if (ret) 1088*3e230dd2SCorentin Chary vs->sasl.waitWriteSSF -= ret; 1089*3e230dd2SCorentin Chary } else 1090*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_SASL */ 1091*3e230dd2SCorentin Chary ret = vnc_client_write_buf(vs, vs->output.buffer, vs->output.offset); 1092*3e230dd2SCorentin Chary if (!ret) 1093*3e230dd2SCorentin Chary return 0; 1094*3e230dd2SCorentin Chary 1095*3e230dd2SCorentin Chary memmove(vs->output.buffer, vs->output.buffer + ret, (vs->output.offset - ret)); 1096*3e230dd2SCorentin Chary vs->output.offset -= ret; 1097*3e230dd2SCorentin Chary 1098*3e230dd2SCorentin Chary if (vs->output.offset == 0) { 1099*3e230dd2SCorentin Chary qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs); 1100*3e230dd2SCorentin Chary } 1101*3e230dd2SCorentin Chary 1102*3e230dd2SCorentin Chary return ret; 1103*3e230dd2SCorentin Chary } 1104*3e230dd2SCorentin Chary 1105*3e230dd2SCorentin Chary 1106*3e230dd2SCorentin Chary /* 1107*3e230dd2SCorentin Chary * First function called whenever there is data to be written to 1108*3e230dd2SCorentin Chary * the client socket. Will delegate actual work according to whether 1109*3e230dd2SCorentin Chary * SASL SSF layers are enabled (thus requiring encryption calls) 1110*3e230dd2SCorentin Chary */ 1111*3e230dd2SCorentin Chary void vnc_client_write(void *opaque) 1112*3e230dd2SCorentin Chary { 1113*3e230dd2SCorentin Chary VncState *vs = opaque; 1114*3e230dd2SCorentin Chary 1115*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL 1116*3e230dd2SCorentin Chary if (vs->sasl.conn && 1117*3e230dd2SCorentin Chary vs->sasl.runSSF && 1118*3e230dd2SCorentin Chary !vs->sasl.waitWriteSSF) { 1119*3e230dd2SCorentin Chary vnc_client_write_sasl(vs); 1120*3e230dd2SCorentin Chary } else 1121*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_SASL */ 1122*3e230dd2SCorentin Chary vnc_client_write_plain(vs); 1123*3e230dd2SCorentin Chary } 1124*3e230dd2SCorentin Chary 1125*3e230dd2SCorentin Chary void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting) 1126*3e230dd2SCorentin Chary { 1127*3e230dd2SCorentin Chary vs->read_handler = func; 1128*3e230dd2SCorentin Chary vs->read_handler_expect = expecting; 1129*3e230dd2SCorentin Chary } 1130*3e230dd2SCorentin Chary 1131*3e230dd2SCorentin Chary 1132*3e230dd2SCorentin Chary /* 1133*3e230dd2SCorentin Chary * Called to read a chunk of data from the client socket. The data may 1134*3e230dd2SCorentin Chary * be the raw data, or may need to be further decoded by SASL. 1135*3e230dd2SCorentin Chary * The data will be read either straight from to the socket, or 1136*3e230dd2SCorentin Chary * read via the GNUTLS wrappers, if TLS/SSL encryption is enabled 1137*3e230dd2SCorentin Chary * 1138*3e230dd2SCorentin Chary * NB, it is theoretically possible to have 2 layers of encryption, 1139*3e230dd2SCorentin Chary * both SASL, and this TLS layer. It is highly unlikely in practice 1140*3e230dd2SCorentin Chary * though, since SASL encryption will typically be a no-op if TLS 1141*3e230dd2SCorentin Chary * is active 1142*3e230dd2SCorentin Chary * 1143*3e230dd2SCorentin Chary * Returns the number of bytes read, which may be less than 1144*3e230dd2SCorentin Chary * the requested 'datalen' if the socket would block. Returns 1145*3e230dd2SCorentin Chary * -1 on error, and disconnects the client socket. 1146*3e230dd2SCorentin Chary */ 1147*3e230dd2SCorentin Chary long vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen) 1148*3e230dd2SCorentin Chary { 1149*3e230dd2SCorentin Chary long ret; 1150*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 1151*3e230dd2SCorentin Chary if (vs->tls.session) { 1152*3e230dd2SCorentin Chary ret = gnutls_read(vs->tls.session, data, datalen); 1153*3e230dd2SCorentin Chary if (ret < 0) { 1154*3e230dd2SCorentin Chary if (ret == GNUTLS_E_AGAIN) 1155*3e230dd2SCorentin Chary errno = EAGAIN; 1156*3e230dd2SCorentin Chary else 1157*3e230dd2SCorentin Chary errno = EIO; 1158*3e230dd2SCorentin Chary ret = -1; 1159*3e230dd2SCorentin Chary } 1160*3e230dd2SCorentin Chary } else 1161*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_TLS */ 1162*3e230dd2SCorentin Chary ret = recv(vs->csock, (void *)data, datalen, 0); 1163*3e230dd2SCorentin Chary VNC_DEBUG("Read wire %p %zd -> %ld\n", data, datalen, ret); 1164*3e230dd2SCorentin Chary return vnc_client_io_error(vs, ret, socket_error()); 1165*3e230dd2SCorentin Chary } 1166*3e230dd2SCorentin Chary 1167*3e230dd2SCorentin Chary 1168*3e230dd2SCorentin Chary /* 1169*3e230dd2SCorentin Chary * Called to read data from the client socket to the input buffer, 1170*3e230dd2SCorentin Chary * when not using any SASL SSF encryption layers. Will read as much 1171*3e230dd2SCorentin Chary * data as possible without blocking. 1172*3e230dd2SCorentin Chary * 1173*3e230dd2SCorentin Chary * Returns the number of bytes read. Returns -1 on error, and 1174*3e230dd2SCorentin Chary * disconnects the client socket. 1175*3e230dd2SCorentin Chary */ 1176*3e230dd2SCorentin Chary static long vnc_client_read_plain(VncState *vs) 1177*3e230dd2SCorentin Chary { 1178*3e230dd2SCorentin Chary int ret; 1179*3e230dd2SCorentin Chary VNC_DEBUG("Read plain %p size %zd offset %zd\n", 1180*3e230dd2SCorentin Chary vs->input.buffer, vs->input.capacity, vs->input.offset); 1181*3e230dd2SCorentin Chary buffer_reserve(&vs->input, 4096); 1182*3e230dd2SCorentin Chary ret = vnc_client_read_buf(vs, buffer_end(&vs->input), 4096); 1183*3e230dd2SCorentin Chary if (!ret) 1184*3e230dd2SCorentin Chary return 0; 1185*3e230dd2SCorentin Chary vs->input.offset += ret; 1186*3e230dd2SCorentin Chary return ret; 1187*3e230dd2SCorentin Chary } 1188*3e230dd2SCorentin Chary 1189*3e230dd2SCorentin Chary 1190*3e230dd2SCorentin Chary /* 1191*3e230dd2SCorentin Chary * First function called whenever there is more data to be read from 1192*3e230dd2SCorentin Chary * the client socket. Will delegate actual work according to whether 1193*3e230dd2SCorentin Chary * SASL SSF layers are enabled (thus requiring decryption calls) 1194*3e230dd2SCorentin Chary */ 1195*3e230dd2SCorentin Chary void vnc_client_read(void *opaque) 1196*3e230dd2SCorentin Chary { 1197*3e230dd2SCorentin Chary VncState *vs = opaque; 1198*3e230dd2SCorentin Chary long ret; 1199*3e230dd2SCorentin Chary 1200*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL 1201*3e230dd2SCorentin Chary if (vs->sasl.conn && vs->sasl.runSSF) 1202*3e230dd2SCorentin Chary ret = vnc_client_read_sasl(vs); 1203*3e230dd2SCorentin Chary else 1204*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_SASL */ 1205*3e230dd2SCorentin Chary ret = vnc_client_read_plain(vs); 1206*3e230dd2SCorentin Chary if (!ret) { 1207*3e230dd2SCorentin Chary if (vs->csock == -1) 1208*3e230dd2SCorentin Chary vnc_disconnect_finish(vs); 1209*3e230dd2SCorentin Chary return; 1210*3e230dd2SCorentin Chary } 1211*3e230dd2SCorentin Chary 1212*3e230dd2SCorentin Chary while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) { 1213*3e230dd2SCorentin Chary size_t len = vs->read_handler_expect; 1214*3e230dd2SCorentin Chary int ret; 1215*3e230dd2SCorentin Chary 1216*3e230dd2SCorentin Chary ret = vs->read_handler(vs, vs->input.buffer, len); 1217*3e230dd2SCorentin Chary if (vs->csock == -1) { 1218*3e230dd2SCorentin Chary vnc_disconnect_finish(vs); 1219*3e230dd2SCorentin Chary return; 1220*3e230dd2SCorentin Chary } 1221*3e230dd2SCorentin Chary 1222*3e230dd2SCorentin Chary if (!ret) { 1223*3e230dd2SCorentin Chary memmove(vs->input.buffer, vs->input.buffer + len, (vs->input.offset - len)); 1224*3e230dd2SCorentin Chary vs->input.offset -= len; 1225*3e230dd2SCorentin Chary } else { 1226*3e230dd2SCorentin Chary vs->read_handler_expect = ret; 1227*3e230dd2SCorentin Chary } 1228*3e230dd2SCorentin Chary } 1229*3e230dd2SCorentin Chary } 1230*3e230dd2SCorentin Chary 1231*3e230dd2SCorentin Chary void vnc_write(VncState *vs, const void *data, size_t len) 1232*3e230dd2SCorentin Chary { 1233*3e230dd2SCorentin Chary buffer_reserve(&vs->output, len); 1234*3e230dd2SCorentin Chary 1235*3e230dd2SCorentin Chary if (vs->csock != -1 && buffer_empty(&vs->output)) { 1236*3e230dd2SCorentin Chary qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs); 1237*3e230dd2SCorentin Chary } 1238*3e230dd2SCorentin Chary 1239*3e230dd2SCorentin Chary buffer_append(&vs->output, data, len); 1240*3e230dd2SCorentin Chary } 1241*3e230dd2SCorentin Chary 1242*3e230dd2SCorentin Chary void vnc_write_s32(VncState *vs, int32_t value) 1243*3e230dd2SCorentin Chary { 1244*3e230dd2SCorentin Chary vnc_write_u32(vs, *(uint32_t *)&value); 1245*3e230dd2SCorentin Chary } 1246*3e230dd2SCorentin Chary 1247*3e230dd2SCorentin Chary void vnc_write_u32(VncState *vs, uint32_t value) 1248*3e230dd2SCorentin Chary { 1249*3e230dd2SCorentin Chary uint8_t buf[4]; 1250*3e230dd2SCorentin Chary 1251*3e230dd2SCorentin Chary buf[0] = (value >> 24) & 0xFF; 1252*3e230dd2SCorentin Chary buf[1] = (value >> 16) & 0xFF; 1253*3e230dd2SCorentin Chary buf[2] = (value >> 8) & 0xFF; 1254*3e230dd2SCorentin Chary buf[3] = value & 0xFF; 1255*3e230dd2SCorentin Chary 1256*3e230dd2SCorentin Chary vnc_write(vs, buf, 4); 1257*3e230dd2SCorentin Chary } 1258*3e230dd2SCorentin Chary 1259*3e230dd2SCorentin Chary void vnc_write_u16(VncState *vs, uint16_t value) 1260*3e230dd2SCorentin Chary { 1261*3e230dd2SCorentin Chary uint8_t buf[2]; 1262*3e230dd2SCorentin Chary 1263*3e230dd2SCorentin Chary buf[0] = (value >> 8) & 0xFF; 1264*3e230dd2SCorentin Chary buf[1] = value & 0xFF; 1265*3e230dd2SCorentin Chary 1266*3e230dd2SCorentin Chary vnc_write(vs, buf, 2); 1267*3e230dd2SCorentin Chary } 1268*3e230dd2SCorentin Chary 1269*3e230dd2SCorentin Chary void vnc_write_u8(VncState *vs, uint8_t value) 1270*3e230dd2SCorentin Chary { 1271*3e230dd2SCorentin Chary vnc_write(vs, (char *)&value, 1); 1272*3e230dd2SCorentin Chary } 1273*3e230dd2SCorentin Chary 1274*3e230dd2SCorentin Chary void vnc_flush(VncState *vs) 1275*3e230dd2SCorentin Chary { 1276*3e230dd2SCorentin Chary if (vs->csock != -1 && vs->output.offset) 1277*3e230dd2SCorentin Chary vnc_client_write(vs); 1278*3e230dd2SCorentin Chary } 1279*3e230dd2SCorentin Chary 1280*3e230dd2SCorentin Chary uint8_t read_u8(uint8_t *data, size_t offset) 1281*3e230dd2SCorentin Chary { 1282*3e230dd2SCorentin Chary return data[offset]; 1283*3e230dd2SCorentin Chary } 1284*3e230dd2SCorentin Chary 1285*3e230dd2SCorentin Chary uint16_t read_u16(uint8_t *data, size_t offset) 1286*3e230dd2SCorentin Chary { 1287*3e230dd2SCorentin Chary return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF); 1288*3e230dd2SCorentin Chary } 1289*3e230dd2SCorentin Chary 1290*3e230dd2SCorentin Chary int32_t read_s32(uint8_t *data, size_t offset) 1291*3e230dd2SCorentin Chary { 1292*3e230dd2SCorentin Chary return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) | 1293*3e230dd2SCorentin Chary (data[offset + 2] << 8) | data[offset + 3]); 1294*3e230dd2SCorentin Chary } 1295*3e230dd2SCorentin Chary 1296*3e230dd2SCorentin Chary uint32_t read_u32(uint8_t *data, size_t offset) 1297*3e230dd2SCorentin Chary { 1298*3e230dd2SCorentin Chary return ((data[offset] << 24) | (data[offset + 1] << 16) | 1299*3e230dd2SCorentin Chary (data[offset + 2] << 8) | data[offset + 3]); 1300*3e230dd2SCorentin Chary } 1301*3e230dd2SCorentin Chary 1302*3e230dd2SCorentin Chary static void client_cut_text(VncState *vs, size_t len, uint8_t *text) 1303*3e230dd2SCorentin Chary { 1304*3e230dd2SCorentin Chary } 1305*3e230dd2SCorentin Chary 1306*3e230dd2SCorentin Chary static void check_pointer_type_change(Notifier *notifier) 1307*3e230dd2SCorentin Chary { 1308*3e230dd2SCorentin Chary VncState *vs = container_of(notifier, VncState, mouse_mode_notifier); 1309*3e230dd2SCorentin Chary int absolute = kbd_mouse_is_absolute(); 1310*3e230dd2SCorentin Chary 1311*3e230dd2SCorentin Chary if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE) && vs->absolute != absolute) { 1312*3e230dd2SCorentin Chary vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); 1313*3e230dd2SCorentin Chary vnc_write_u8(vs, 0); 1314*3e230dd2SCorentin Chary vnc_write_u16(vs, 1); 1315*3e230dd2SCorentin Chary vnc_framebuffer_update(vs, absolute, 0, 1316*3e230dd2SCorentin Chary ds_get_width(vs->ds), ds_get_height(vs->ds), 1317*3e230dd2SCorentin Chary VNC_ENCODING_POINTER_TYPE_CHANGE); 1318*3e230dd2SCorentin Chary vnc_flush(vs); 1319*3e230dd2SCorentin Chary } 1320*3e230dd2SCorentin Chary vs->absolute = absolute; 1321*3e230dd2SCorentin Chary } 1322*3e230dd2SCorentin Chary 1323*3e230dd2SCorentin Chary static void pointer_event(VncState *vs, int button_mask, int x, int y) 1324*3e230dd2SCorentin Chary { 1325*3e230dd2SCorentin Chary int buttons = 0; 1326*3e230dd2SCorentin Chary int dz = 0; 1327*3e230dd2SCorentin Chary 1328*3e230dd2SCorentin Chary if (button_mask & 0x01) 1329*3e230dd2SCorentin Chary buttons |= MOUSE_EVENT_LBUTTON; 1330*3e230dd2SCorentin Chary if (button_mask & 0x02) 1331*3e230dd2SCorentin Chary buttons |= MOUSE_EVENT_MBUTTON; 1332*3e230dd2SCorentin Chary if (button_mask & 0x04) 1333*3e230dd2SCorentin Chary buttons |= MOUSE_EVENT_RBUTTON; 1334*3e230dd2SCorentin Chary if (button_mask & 0x08) 1335*3e230dd2SCorentin Chary dz = -1; 1336*3e230dd2SCorentin Chary if (button_mask & 0x10) 1337*3e230dd2SCorentin Chary dz = 1; 1338*3e230dd2SCorentin Chary 1339*3e230dd2SCorentin Chary if (vs->absolute) { 1340*3e230dd2SCorentin Chary kbd_mouse_event(ds_get_width(vs->ds) > 1 ? 1341*3e230dd2SCorentin Chary x * 0x7FFF / (ds_get_width(vs->ds) - 1) : 0x4000, 1342*3e230dd2SCorentin Chary ds_get_height(vs->ds) > 1 ? 1343*3e230dd2SCorentin Chary y * 0x7FFF / (ds_get_height(vs->ds) - 1) : 0x4000, 1344*3e230dd2SCorentin Chary dz, buttons); 1345*3e230dd2SCorentin Chary } else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) { 1346*3e230dd2SCorentin Chary x -= 0x7FFF; 1347*3e230dd2SCorentin Chary y -= 0x7FFF; 1348*3e230dd2SCorentin Chary 1349*3e230dd2SCorentin Chary kbd_mouse_event(x, y, dz, buttons); 1350*3e230dd2SCorentin Chary } else { 1351*3e230dd2SCorentin Chary if (vs->last_x != -1) 1352*3e230dd2SCorentin Chary kbd_mouse_event(x - vs->last_x, 1353*3e230dd2SCorentin Chary y - vs->last_y, 1354*3e230dd2SCorentin Chary dz, buttons); 1355*3e230dd2SCorentin Chary vs->last_x = x; 1356*3e230dd2SCorentin Chary vs->last_y = y; 1357*3e230dd2SCorentin Chary } 1358*3e230dd2SCorentin Chary } 1359*3e230dd2SCorentin Chary 1360*3e230dd2SCorentin Chary static void reset_keys(VncState *vs) 1361*3e230dd2SCorentin Chary { 1362*3e230dd2SCorentin Chary int i; 1363*3e230dd2SCorentin Chary for(i = 0; i < 256; i++) { 1364*3e230dd2SCorentin Chary if (vs->modifiers_state[i]) { 1365*3e230dd2SCorentin Chary if (i & SCANCODE_GREY) 1366*3e230dd2SCorentin Chary kbd_put_keycode(SCANCODE_EMUL0); 1367*3e230dd2SCorentin Chary kbd_put_keycode(i | SCANCODE_UP); 1368*3e230dd2SCorentin Chary vs->modifiers_state[i] = 0; 1369*3e230dd2SCorentin Chary } 1370*3e230dd2SCorentin Chary } 1371*3e230dd2SCorentin Chary } 1372*3e230dd2SCorentin Chary 1373*3e230dd2SCorentin Chary static void press_key(VncState *vs, int keysym) 1374*3e230dd2SCorentin Chary { 1375*3e230dd2SCorentin Chary int keycode = keysym2scancode(vs->vd->kbd_layout, keysym) & SCANCODE_KEYMASK; 1376*3e230dd2SCorentin Chary if (keycode & SCANCODE_GREY) 1377*3e230dd2SCorentin Chary kbd_put_keycode(SCANCODE_EMUL0); 1378*3e230dd2SCorentin Chary kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK); 1379*3e230dd2SCorentin Chary if (keycode & SCANCODE_GREY) 1380*3e230dd2SCorentin Chary kbd_put_keycode(SCANCODE_EMUL0); 1381*3e230dd2SCorentin Chary kbd_put_keycode(keycode | SCANCODE_UP); 1382*3e230dd2SCorentin Chary } 1383*3e230dd2SCorentin Chary 1384*3e230dd2SCorentin Chary static void kbd_leds(void *opaque, int ledstate) 1385*3e230dd2SCorentin Chary { 1386*3e230dd2SCorentin Chary VncState *vs = opaque; 1387*3e230dd2SCorentin Chary int caps, num; 1388*3e230dd2SCorentin Chary 1389*3e230dd2SCorentin Chary caps = ledstate & QEMU_CAPS_LOCK_LED ? 1 : 0; 1390*3e230dd2SCorentin Chary num = ledstate & QEMU_NUM_LOCK_LED ? 1 : 0; 1391*3e230dd2SCorentin Chary 1392*3e230dd2SCorentin Chary if (vs->modifiers_state[0x3a] != caps) { 1393*3e230dd2SCorentin Chary vs->modifiers_state[0x3a] = caps; 1394*3e230dd2SCorentin Chary } 1395*3e230dd2SCorentin Chary if (vs->modifiers_state[0x45] != num) { 1396*3e230dd2SCorentin Chary vs->modifiers_state[0x45] = num; 1397*3e230dd2SCorentin Chary } 1398*3e230dd2SCorentin Chary } 1399*3e230dd2SCorentin Chary 1400*3e230dd2SCorentin Chary static void do_key_event(VncState *vs, int down, int keycode, int sym) 1401*3e230dd2SCorentin Chary { 1402*3e230dd2SCorentin Chary /* QEMU console switch */ 1403*3e230dd2SCorentin Chary switch(keycode) { 1404*3e230dd2SCorentin Chary case 0x2a: /* Left Shift */ 1405*3e230dd2SCorentin Chary case 0x36: /* Right Shift */ 1406*3e230dd2SCorentin Chary case 0x1d: /* Left CTRL */ 1407*3e230dd2SCorentin Chary case 0x9d: /* Right CTRL */ 1408*3e230dd2SCorentin Chary case 0x38: /* Left ALT */ 1409*3e230dd2SCorentin Chary case 0xb8: /* Right ALT */ 1410*3e230dd2SCorentin Chary if (down) 1411*3e230dd2SCorentin Chary vs->modifiers_state[keycode] = 1; 1412*3e230dd2SCorentin Chary else 1413*3e230dd2SCorentin Chary vs->modifiers_state[keycode] = 0; 1414*3e230dd2SCorentin Chary break; 1415*3e230dd2SCorentin Chary case 0x02 ... 0x0a: /* '1' to '9' keys */ 1416*3e230dd2SCorentin Chary if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) { 1417*3e230dd2SCorentin Chary /* Reset the modifiers sent to the current console */ 1418*3e230dd2SCorentin Chary reset_keys(vs); 1419*3e230dd2SCorentin Chary console_select(keycode - 0x02); 1420*3e230dd2SCorentin Chary return; 1421*3e230dd2SCorentin Chary } 1422*3e230dd2SCorentin Chary break; 1423*3e230dd2SCorentin Chary case 0x3a: /* CapsLock */ 1424*3e230dd2SCorentin Chary case 0x45: /* NumLock */ 1425*3e230dd2SCorentin Chary if (down) 1426*3e230dd2SCorentin Chary vs->modifiers_state[keycode] ^= 1; 1427*3e230dd2SCorentin Chary break; 1428*3e230dd2SCorentin Chary } 1429*3e230dd2SCorentin Chary 1430*3e230dd2SCorentin Chary if (vs->vd->lock_key_sync && 1431*3e230dd2SCorentin Chary keycode_is_keypad(vs->vd->kbd_layout, keycode)) { 1432*3e230dd2SCorentin Chary /* If the numlock state needs to change then simulate an additional 1433*3e230dd2SCorentin Chary keypress before sending this one. This will happen if the user 1434*3e230dd2SCorentin Chary toggles numlock away from the VNC window. 1435*3e230dd2SCorentin Chary */ 1436*3e230dd2SCorentin Chary if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) { 1437*3e230dd2SCorentin Chary if (!vs->modifiers_state[0x45]) { 1438*3e230dd2SCorentin Chary vs->modifiers_state[0x45] = 1; 1439*3e230dd2SCorentin Chary press_key(vs, 0xff7f); 1440*3e230dd2SCorentin Chary } 1441*3e230dd2SCorentin Chary } else { 1442*3e230dd2SCorentin Chary if (vs->modifiers_state[0x45]) { 1443*3e230dd2SCorentin Chary vs->modifiers_state[0x45] = 0; 1444*3e230dd2SCorentin Chary press_key(vs, 0xff7f); 1445*3e230dd2SCorentin Chary } 1446*3e230dd2SCorentin Chary } 1447*3e230dd2SCorentin Chary } 1448*3e230dd2SCorentin Chary 1449*3e230dd2SCorentin Chary if (vs->vd->lock_key_sync && 1450*3e230dd2SCorentin Chary ((sym >= 'A' && sym <= 'Z') || (sym >= 'a' && sym <= 'z'))) { 1451*3e230dd2SCorentin Chary /* If the capslock state needs to change then simulate an additional 1452*3e230dd2SCorentin Chary keypress before sending this one. This will happen if the user 1453*3e230dd2SCorentin Chary toggles capslock away from the VNC window. 1454*3e230dd2SCorentin Chary */ 1455*3e230dd2SCorentin Chary int uppercase = !!(sym >= 'A' && sym <= 'Z'); 1456*3e230dd2SCorentin Chary int shift = !!(vs->modifiers_state[0x2a] | vs->modifiers_state[0x36]); 1457*3e230dd2SCorentin Chary int capslock = !!(vs->modifiers_state[0x3a]); 1458*3e230dd2SCorentin Chary if (capslock) { 1459*3e230dd2SCorentin Chary if (uppercase == shift) { 1460*3e230dd2SCorentin Chary vs->modifiers_state[0x3a] = 0; 1461*3e230dd2SCorentin Chary press_key(vs, 0xffe5); 1462*3e230dd2SCorentin Chary } 1463*3e230dd2SCorentin Chary } else { 1464*3e230dd2SCorentin Chary if (uppercase != shift) { 1465*3e230dd2SCorentin Chary vs->modifiers_state[0x3a] = 1; 1466*3e230dd2SCorentin Chary press_key(vs, 0xffe5); 1467*3e230dd2SCorentin Chary } 1468*3e230dd2SCorentin Chary } 1469*3e230dd2SCorentin Chary } 1470*3e230dd2SCorentin Chary 1471*3e230dd2SCorentin Chary if (is_graphic_console()) { 1472*3e230dd2SCorentin Chary if (keycode & SCANCODE_GREY) 1473*3e230dd2SCorentin Chary kbd_put_keycode(SCANCODE_EMUL0); 1474*3e230dd2SCorentin Chary if (down) 1475*3e230dd2SCorentin Chary kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK); 1476*3e230dd2SCorentin Chary else 1477*3e230dd2SCorentin Chary kbd_put_keycode(keycode | SCANCODE_UP); 1478*3e230dd2SCorentin Chary } else { 1479*3e230dd2SCorentin Chary /* QEMU console emulation */ 1480*3e230dd2SCorentin Chary if (down) { 1481*3e230dd2SCorentin Chary int numlock = vs->modifiers_state[0x45]; 1482*3e230dd2SCorentin Chary switch (keycode) { 1483*3e230dd2SCorentin Chary case 0x2a: /* Left Shift */ 1484*3e230dd2SCorentin Chary case 0x36: /* Right Shift */ 1485*3e230dd2SCorentin Chary case 0x1d: /* Left CTRL */ 1486*3e230dd2SCorentin Chary case 0x9d: /* Right CTRL */ 1487*3e230dd2SCorentin Chary case 0x38: /* Left ALT */ 1488*3e230dd2SCorentin Chary case 0xb8: /* Right ALT */ 1489*3e230dd2SCorentin Chary break; 1490*3e230dd2SCorentin Chary case 0xc8: 1491*3e230dd2SCorentin Chary kbd_put_keysym(QEMU_KEY_UP); 1492*3e230dd2SCorentin Chary break; 1493*3e230dd2SCorentin Chary case 0xd0: 1494*3e230dd2SCorentin Chary kbd_put_keysym(QEMU_KEY_DOWN); 1495*3e230dd2SCorentin Chary break; 1496*3e230dd2SCorentin Chary case 0xcb: 1497*3e230dd2SCorentin Chary kbd_put_keysym(QEMU_KEY_LEFT); 1498*3e230dd2SCorentin Chary break; 1499*3e230dd2SCorentin Chary case 0xcd: 1500*3e230dd2SCorentin Chary kbd_put_keysym(QEMU_KEY_RIGHT); 1501*3e230dd2SCorentin Chary break; 1502*3e230dd2SCorentin Chary case 0xd3: 1503*3e230dd2SCorentin Chary kbd_put_keysym(QEMU_KEY_DELETE); 1504*3e230dd2SCorentin Chary break; 1505*3e230dd2SCorentin Chary case 0xc7: 1506*3e230dd2SCorentin Chary kbd_put_keysym(QEMU_KEY_HOME); 1507*3e230dd2SCorentin Chary break; 1508*3e230dd2SCorentin Chary case 0xcf: 1509*3e230dd2SCorentin Chary kbd_put_keysym(QEMU_KEY_END); 1510*3e230dd2SCorentin Chary break; 1511*3e230dd2SCorentin Chary case 0xc9: 1512*3e230dd2SCorentin Chary kbd_put_keysym(QEMU_KEY_PAGEUP); 1513*3e230dd2SCorentin Chary break; 1514*3e230dd2SCorentin Chary case 0xd1: 1515*3e230dd2SCorentin Chary kbd_put_keysym(QEMU_KEY_PAGEDOWN); 1516*3e230dd2SCorentin Chary break; 1517*3e230dd2SCorentin Chary 1518*3e230dd2SCorentin Chary case 0x47: 1519*3e230dd2SCorentin Chary kbd_put_keysym(numlock ? '7' : QEMU_KEY_HOME); 1520*3e230dd2SCorentin Chary break; 1521*3e230dd2SCorentin Chary case 0x48: 1522*3e230dd2SCorentin Chary kbd_put_keysym(numlock ? '8' : QEMU_KEY_UP); 1523*3e230dd2SCorentin Chary break; 1524*3e230dd2SCorentin Chary case 0x49: 1525*3e230dd2SCorentin Chary kbd_put_keysym(numlock ? '9' : QEMU_KEY_PAGEUP); 1526*3e230dd2SCorentin Chary break; 1527*3e230dd2SCorentin Chary case 0x4b: 1528*3e230dd2SCorentin Chary kbd_put_keysym(numlock ? '4' : QEMU_KEY_LEFT); 1529*3e230dd2SCorentin Chary break; 1530*3e230dd2SCorentin Chary case 0x4c: 1531*3e230dd2SCorentin Chary kbd_put_keysym('5'); 1532*3e230dd2SCorentin Chary break; 1533*3e230dd2SCorentin Chary case 0x4d: 1534*3e230dd2SCorentin Chary kbd_put_keysym(numlock ? '6' : QEMU_KEY_RIGHT); 1535*3e230dd2SCorentin Chary break; 1536*3e230dd2SCorentin Chary case 0x4f: 1537*3e230dd2SCorentin Chary kbd_put_keysym(numlock ? '1' : QEMU_KEY_END); 1538*3e230dd2SCorentin Chary break; 1539*3e230dd2SCorentin Chary case 0x50: 1540*3e230dd2SCorentin Chary kbd_put_keysym(numlock ? '2' : QEMU_KEY_DOWN); 1541*3e230dd2SCorentin Chary break; 1542*3e230dd2SCorentin Chary case 0x51: 1543*3e230dd2SCorentin Chary kbd_put_keysym(numlock ? '3' : QEMU_KEY_PAGEDOWN); 1544*3e230dd2SCorentin Chary break; 1545*3e230dd2SCorentin Chary case 0x52: 1546*3e230dd2SCorentin Chary kbd_put_keysym('0'); 1547*3e230dd2SCorentin Chary break; 1548*3e230dd2SCorentin Chary case 0x53: 1549*3e230dd2SCorentin Chary kbd_put_keysym(numlock ? '.' : QEMU_KEY_DELETE); 1550*3e230dd2SCorentin Chary break; 1551*3e230dd2SCorentin Chary 1552*3e230dd2SCorentin Chary case 0xb5: 1553*3e230dd2SCorentin Chary kbd_put_keysym('/'); 1554*3e230dd2SCorentin Chary break; 1555*3e230dd2SCorentin Chary case 0x37: 1556*3e230dd2SCorentin Chary kbd_put_keysym('*'); 1557*3e230dd2SCorentin Chary break; 1558*3e230dd2SCorentin Chary case 0x4a: 1559*3e230dd2SCorentin Chary kbd_put_keysym('-'); 1560*3e230dd2SCorentin Chary break; 1561*3e230dd2SCorentin Chary case 0x4e: 1562*3e230dd2SCorentin Chary kbd_put_keysym('+'); 1563*3e230dd2SCorentin Chary break; 1564*3e230dd2SCorentin Chary case 0x9c: 1565*3e230dd2SCorentin Chary kbd_put_keysym('\n'); 1566*3e230dd2SCorentin Chary break; 1567*3e230dd2SCorentin Chary 1568*3e230dd2SCorentin Chary default: 1569*3e230dd2SCorentin Chary kbd_put_keysym(sym); 1570*3e230dd2SCorentin Chary break; 1571*3e230dd2SCorentin Chary } 1572*3e230dd2SCorentin Chary } 1573*3e230dd2SCorentin Chary } 1574*3e230dd2SCorentin Chary } 1575*3e230dd2SCorentin Chary 1576*3e230dd2SCorentin Chary static void key_event(VncState *vs, int down, uint32_t sym) 1577*3e230dd2SCorentin Chary { 1578*3e230dd2SCorentin Chary int keycode; 1579*3e230dd2SCorentin Chary int lsym = sym; 1580*3e230dd2SCorentin Chary 1581*3e230dd2SCorentin Chary if (lsym >= 'A' && lsym <= 'Z' && is_graphic_console()) { 1582*3e230dd2SCorentin Chary lsym = lsym - 'A' + 'a'; 1583*3e230dd2SCorentin Chary } 1584*3e230dd2SCorentin Chary 1585*3e230dd2SCorentin Chary keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF) & SCANCODE_KEYMASK; 1586*3e230dd2SCorentin Chary do_key_event(vs, down, keycode, sym); 1587*3e230dd2SCorentin Chary } 1588*3e230dd2SCorentin Chary 1589*3e230dd2SCorentin Chary static void ext_key_event(VncState *vs, int down, 1590*3e230dd2SCorentin Chary uint32_t sym, uint16_t keycode) 1591*3e230dd2SCorentin Chary { 1592*3e230dd2SCorentin Chary /* if the user specifies a keyboard layout, always use it */ 1593*3e230dd2SCorentin Chary if (keyboard_layout) 1594*3e230dd2SCorentin Chary key_event(vs, down, sym); 1595*3e230dd2SCorentin Chary else 1596*3e230dd2SCorentin Chary do_key_event(vs, down, keycode, sym); 1597*3e230dd2SCorentin Chary } 1598*3e230dd2SCorentin Chary 1599*3e230dd2SCorentin Chary static void framebuffer_update_request(VncState *vs, int incremental, 1600*3e230dd2SCorentin Chary int x_position, int y_position, 1601*3e230dd2SCorentin Chary int w, int h) 1602*3e230dd2SCorentin Chary { 1603*3e230dd2SCorentin Chary if (y_position > ds_get_height(vs->ds)) 1604*3e230dd2SCorentin Chary y_position = ds_get_height(vs->ds); 1605*3e230dd2SCorentin Chary if (y_position + h >= ds_get_height(vs->ds)) 1606*3e230dd2SCorentin Chary h = ds_get_height(vs->ds) - y_position; 1607*3e230dd2SCorentin Chary 1608*3e230dd2SCorentin Chary int i; 1609*3e230dd2SCorentin Chary vs->need_update = 1; 1610*3e230dd2SCorentin Chary if (!incremental) { 1611*3e230dd2SCorentin Chary vs->force_update = 1; 1612*3e230dd2SCorentin Chary for (i = 0; i < h; i++) { 1613*3e230dd2SCorentin Chary vnc_set_bits(vs->dirty[y_position + i], 1614*3e230dd2SCorentin Chary (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS); 1615*3e230dd2SCorentin Chary } 1616*3e230dd2SCorentin Chary } 1617*3e230dd2SCorentin Chary } 1618*3e230dd2SCorentin Chary 1619*3e230dd2SCorentin Chary static void send_ext_key_event_ack(VncState *vs) 1620*3e230dd2SCorentin Chary { 1621*3e230dd2SCorentin Chary vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); 1622*3e230dd2SCorentin Chary vnc_write_u8(vs, 0); 1623*3e230dd2SCorentin Chary vnc_write_u16(vs, 1); 1624*3e230dd2SCorentin Chary vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds), 1625*3e230dd2SCorentin Chary VNC_ENCODING_EXT_KEY_EVENT); 1626*3e230dd2SCorentin Chary vnc_flush(vs); 1627*3e230dd2SCorentin Chary } 1628*3e230dd2SCorentin Chary 1629*3e230dd2SCorentin Chary static void send_ext_audio_ack(VncState *vs) 1630*3e230dd2SCorentin Chary { 1631*3e230dd2SCorentin Chary vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); 1632*3e230dd2SCorentin Chary vnc_write_u8(vs, 0); 1633*3e230dd2SCorentin Chary vnc_write_u16(vs, 1); 1634*3e230dd2SCorentin Chary vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds), 1635*3e230dd2SCorentin Chary VNC_ENCODING_AUDIO); 1636*3e230dd2SCorentin Chary vnc_flush(vs); 1637*3e230dd2SCorentin Chary } 1638*3e230dd2SCorentin Chary 1639*3e230dd2SCorentin Chary static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) 1640*3e230dd2SCorentin Chary { 1641*3e230dd2SCorentin Chary int i; 1642*3e230dd2SCorentin Chary unsigned int enc = 0; 1643*3e230dd2SCorentin Chary 1644*3e230dd2SCorentin Chary vs->features = 0; 1645*3e230dd2SCorentin Chary vs->vnc_encoding = 0; 1646*3e230dd2SCorentin Chary vs->tight_compression = 9; 1647*3e230dd2SCorentin Chary vs->tight_quality = -1; /* Lossless by default */ 1648*3e230dd2SCorentin Chary vs->absolute = -1; 1649*3e230dd2SCorentin Chary 1650*3e230dd2SCorentin Chary /* 1651*3e230dd2SCorentin Chary * Start from the end because the encodings are sent in order of preference. 1652*3e230dd2SCorentin Chary * This way the prefered encoding (first encoding defined in the array) 1653*3e230dd2SCorentin Chary * will be set at the end of the loop. 1654*3e230dd2SCorentin Chary */ 1655*3e230dd2SCorentin Chary for (i = n_encodings - 1; i >= 0; i--) { 1656*3e230dd2SCorentin Chary enc = encodings[i]; 1657*3e230dd2SCorentin Chary switch (enc) { 1658*3e230dd2SCorentin Chary case VNC_ENCODING_RAW: 1659*3e230dd2SCorentin Chary vs->vnc_encoding = enc; 1660*3e230dd2SCorentin Chary break; 1661*3e230dd2SCorentin Chary case VNC_ENCODING_COPYRECT: 1662*3e230dd2SCorentin Chary vs->features |= VNC_FEATURE_COPYRECT_MASK; 1663*3e230dd2SCorentin Chary break; 1664*3e230dd2SCorentin Chary case VNC_ENCODING_HEXTILE: 1665*3e230dd2SCorentin Chary vs->features |= VNC_FEATURE_HEXTILE_MASK; 1666*3e230dd2SCorentin Chary vs->vnc_encoding = enc; 1667*3e230dd2SCorentin Chary break; 1668*3e230dd2SCorentin Chary case VNC_ENCODING_TIGHT: 1669*3e230dd2SCorentin Chary vs->features |= VNC_FEATURE_TIGHT_MASK; 1670*3e230dd2SCorentin Chary vs->vnc_encoding = enc; 1671*3e230dd2SCorentin Chary break; 1672*3e230dd2SCorentin Chary case VNC_ENCODING_ZLIB: 1673*3e230dd2SCorentin Chary vs->features |= VNC_FEATURE_ZLIB_MASK; 1674*3e230dd2SCorentin Chary vs->vnc_encoding = enc; 1675*3e230dd2SCorentin Chary break; 1676*3e230dd2SCorentin Chary case VNC_ENCODING_DESKTOPRESIZE: 1677*3e230dd2SCorentin Chary vs->features |= VNC_FEATURE_RESIZE_MASK; 1678*3e230dd2SCorentin Chary break; 1679*3e230dd2SCorentin Chary case VNC_ENCODING_POINTER_TYPE_CHANGE: 1680*3e230dd2SCorentin Chary vs->features |= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK; 1681*3e230dd2SCorentin Chary break; 1682*3e230dd2SCorentin Chary case VNC_ENCODING_RICH_CURSOR: 1683*3e230dd2SCorentin Chary vs->features |= VNC_FEATURE_RICH_CURSOR_MASK; 1684*3e230dd2SCorentin Chary break; 1685*3e230dd2SCorentin Chary case VNC_ENCODING_EXT_KEY_EVENT: 1686*3e230dd2SCorentin Chary send_ext_key_event_ack(vs); 1687*3e230dd2SCorentin Chary break; 1688*3e230dd2SCorentin Chary case VNC_ENCODING_AUDIO: 1689*3e230dd2SCorentin Chary send_ext_audio_ack(vs); 1690*3e230dd2SCorentin Chary break; 1691*3e230dd2SCorentin Chary case VNC_ENCODING_WMVi: 1692*3e230dd2SCorentin Chary vs->features |= VNC_FEATURE_WMVI_MASK; 1693*3e230dd2SCorentin Chary break; 1694*3e230dd2SCorentin Chary case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9: 1695*3e230dd2SCorentin Chary vs->tight_compression = (enc & 0x0F); 1696*3e230dd2SCorentin Chary break; 1697*3e230dd2SCorentin Chary case VNC_ENCODING_QUALITYLEVEL0 ... VNC_ENCODING_QUALITYLEVEL0 + 9: 1698*3e230dd2SCorentin Chary vs->tight_quality = (enc & 0x0F); 1699*3e230dd2SCorentin Chary break; 1700*3e230dd2SCorentin Chary default: 1701*3e230dd2SCorentin Chary VNC_DEBUG("Unknown encoding: %d (0x%.8x): %d\n", i, enc, enc); 1702*3e230dd2SCorentin Chary break; 1703*3e230dd2SCorentin Chary } 1704*3e230dd2SCorentin Chary } 1705*3e230dd2SCorentin Chary vnc_desktop_resize(vs); 1706*3e230dd2SCorentin Chary check_pointer_type_change(&vs->mouse_mode_notifier); 1707*3e230dd2SCorentin Chary } 1708*3e230dd2SCorentin Chary 1709*3e230dd2SCorentin Chary static void set_pixel_conversion(VncState *vs) 1710*3e230dd2SCorentin Chary { 1711*3e230dd2SCorentin Chary if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) == 1712*3e230dd2SCorentin Chary (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) && 1713*3e230dd2SCorentin Chary !memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) { 1714*3e230dd2SCorentin Chary vs->write_pixels = vnc_write_pixels_copy; 1715*3e230dd2SCorentin Chary vnc_hextile_set_pixel_conversion(vs, 0); 1716*3e230dd2SCorentin Chary } else { 1717*3e230dd2SCorentin Chary vs->write_pixels = vnc_write_pixels_generic; 1718*3e230dd2SCorentin Chary vnc_hextile_set_pixel_conversion(vs, 1); 1719*3e230dd2SCorentin Chary } 1720*3e230dd2SCorentin Chary } 1721*3e230dd2SCorentin Chary 1722*3e230dd2SCorentin Chary static void set_pixel_format(VncState *vs, 1723*3e230dd2SCorentin Chary int bits_per_pixel, int depth, 1724*3e230dd2SCorentin Chary int big_endian_flag, int true_color_flag, 1725*3e230dd2SCorentin Chary int red_max, int green_max, int blue_max, 1726*3e230dd2SCorentin Chary int red_shift, int green_shift, int blue_shift) 1727*3e230dd2SCorentin Chary { 1728*3e230dd2SCorentin Chary if (!true_color_flag) { 1729*3e230dd2SCorentin Chary vnc_client_error(vs); 1730*3e230dd2SCorentin Chary return; 1731*3e230dd2SCorentin Chary } 1732*3e230dd2SCorentin Chary 1733*3e230dd2SCorentin Chary vs->clientds = *(vs->vd->guest.ds); 1734*3e230dd2SCorentin Chary vs->clientds.pf.rmax = red_max; 1735*3e230dd2SCorentin Chary count_bits(vs->clientds.pf.rbits, red_max); 1736*3e230dd2SCorentin Chary vs->clientds.pf.rshift = red_shift; 1737*3e230dd2SCorentin Chary vs->clientds.pf.rmask = red_max << red_shift; 1738*3e230dd2SCorentin Chary vs->clientds.pf.gmax = green_max; 1739*3e230dd2SCorentin Chary count_bits(vs->clientds.pf.gbits, green_max); 1740*3e230dd2SCorentin Chary vs->clientds.pf.gshift = green_shift; 1741*3e230dd2SCorentin Chary vs->clientds.pf.gmask = green_max << green_shift; 1742*3e230dd2SCorentin Chary vs->clientds.pf.bmax = blue_max; 1743*3e230dd2SCorentin Chary count_bits(vs->clientds.pf.bbits, blue_max); 1744*3e230dd2SCorentin Chary vs->clientds.pf.bshift = blue_shift; 1745*3e230dd2SCorentin Chary vs->clientds.pf.bmask = blue_max << blue_shift; 1746*3e230dd2SCorentin Chary vs->clientds.pf.bits_per_pixel = bits_per_pixel; 1747*3e230dd2SCorentin Chary vs->clientds.pf.bytes_per_pixel = bits_per_pixel / 8; 1748*3e230dd2SCorentin Chary vs->clientds.pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel; 1749*3e230dd2SCorentin Chary vs->clientds.flags = big_endian_flag ? QEMU_BIG_ENDIAN_FLAG : 0x00; 1750*3e230dd2SCorentin Chary 1751*3e230dd2SCorentin Chary set_pixel_conversion(vs); 1752*3e230dd2SCorentin Chary 1753*3e230dd2SCorentin Chary vga_hw_invalidate(); 1754*3e230dd2SCorentin Chary vga_hw_update(); 1755*3e230dd2SCorentin Chary } 1756*3e230dd2SCorentin Chary 1757*3e230dd2SCorentin Chary static void pixel_format_message (VncState *vs) { 1758*3e230dd2SCorentin Chary char pad[3] = { 0, 0, 0 }; 1759*3e230dd2SCorentin Chary 1760*3e230dd2SCorentin Chary vnc_write_u8(vs, vs->ds->surface->pf.bits_per_pixel); /* bits-per-pixel */ 1761*3e230dd2SCorentin Chary vnc_write_u8(vs, vs->ds->surface->pf.depth); /* depth */ 1762*3e230dd2SCorentin Chary 1763*3e230dd2SCorentin Chary #ifdef HOST_WORDS_BIGENDIAN 1764*3e230dd2SCorentin Chary vnc_write_u8(vs, 1); /* big-endian-flag */ 1765*3e230dd2SCorentin Chary #else 1766*3e230dd2SCorentin Chary vnc_write_u8(vs, 0); /* big-endian-flag */ 1767*3e230dd2SCorentin Chary #endif 1768*3e230dd2SCorentin Chary vnc_write_u8(vs, 1); /* true-color-flag */ 1769*3e230dd2SCorentin Chary vnc_write_u16(vs, vs->ds->surface->pf.rmax); /* red-max */ 1770*3e230dd2SCorentin Chary vnc_write_u16(vs, vs->ds->surface->pf.gmax); /* green-max */ 1771*3e230dd2SCorentin Chary vnc_write_u16(vs, vs->ds->surface->pf.bmax); /* blue-max */ 1772*3e230dd2SCorentin Chary vnc_write_u8(vs, vs->ds->surface->pf.rshift); /* red-shift */ 1773*3e230dd2SCorentin Chary vnc_write_u8(vs, vs->ds->surface->pf.gshift); /* green-shift */ 1774*3e230dd2SCorentin Chary vnc_write_u8(vs, vs->ds->surface->pf.bshift); /* blue-shift */ 1775*3e230dd2SCorentin Chary 1776*3e230dd2SCorentin Chary vnc_hextile_set_pixel_conversion(vs, 0); 1777*3e230dd2SCorentin Chary 1778*3e230dd2SCorentin Chary vs->clientds = *(vs->ds->surface); 1779*3e230dd2SCorentin Chary vs->clientds.flags &= ~QEMU_ALLOCATED_FLAG; 1780*3e230dd2SCorentin Chary vs->write_pixels = vnc_write_pixels_copy; 1781*3e230dd2SCorentin Chary 1782*3e230dd2SCorentin Chary vnc_write(vs, pad, 3); /* padding */ 1783*3e230dd2SCorentin Chary } 1784*3e230dd2SCorentin Chary 1785*3e230dd2SCorentin Chary static void vnc_dpy_setdata(DisplayState *ds) 1786*3e230dd2SCorentin Chary { 1787*3e230dd2SCorentin Chary /* We don't have to do anything */ 1788*3e230dd2SCorentin Chary } 1789*3e230dd2SCorentin Chary 1790*3e230dd2SCorentin Chary static void vnc_colordepth(VncState *vs) 1791*3e230dd2SCorentin Chary { 1792*3e230dd2SCorentin Chary if (vnc_has_feature(vs, VNC_FEATURE_WMVI)) { 1793*3e230dd2SCorentin Chary /* Sending a WMVi message to notify the client*/ 1794*3e230dd2SCorentin Chary vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); 1795*3e230dd2SCorentin Chary vnc_write_u8(vs, 0); 1796*3e230dd2SCorentin Chary vnc_write_u16(vs, 1); /* number of rects */ 1797*3e230dd2SCorentin Chary vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), 1798*3e230dd2SCorentin Chary ds_get_height(vs->ds), VNC_ENCODING_WMVi); 1799*3e230dd2SCorentin Chary pixel_format_message(vs); 1800*3e230dd2SCorentin Chary vnc_flush(vs); 1801*3e230dd2SCorentin Chary } else { 1802*3e230dd2SCorentin Chary set_pixel_conversion(vs); 1803*3e230dd2SCorentin Chary } 1804*3e230dd2SCorentin Chary } 1805*3e230dd2SCorentin Chary 1806*3e230dd2SCorentin Chary static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len) 1807*3e230dd2SCorentin Chary { 1808*3e230dd2SCorentin Chary int i; 1809*3e230dd2SCorentin Chary uint16_t limit; 1810*3e230dd2SCorentin Chary VncDisplay *vd = vs->vd; 1811*3e230dd2SCorentin Chary 1812*3e230dd2SCorentin Chary if (data[0] > 3) { 1813*3e230dd2SCorentin Chary vd->timer_interval = VNC_REFRESH_INTERVAL_BASE; 1814*3e230dd2SCorentin Chary if (!qemu_timer_expired(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval)) 1815*3e230dd2SCorentin Chary qemu_mod_timer(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval); 1816*3e230dd2SCorentin Chary } 1817*3e230dd2SCorentin Chary 1818*3e230dd2SCorentin Chary switch (data[0]) { 1819*3e230dd2SCorentin Chary case VNC_MSG_CLIENT_SET_PIXEL_FORMAT: 1820*3e230dd2SCorentin Chary if (len == 1) 1821*3e230dd2SCorentin Chary return 20; 1822*3e230dd2SCorentin Chary 1823*3e230dd2SCorentin Chary set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5), 1824*3e230dd2SCorentin Chary read_u8(data, 6), read_u8(data, 7), 1825*3e230dd2SCorentin Chary read_u16(data, 8), read_u16(data, 10), 1826*3e230dd2SCorentin Chary read_u16(data, 12), read_u8(data, 14), 1827*3e230dd2SCorentin Chary read_u8(data, 15), read_u8(data, 16)); 1828*3e230dd2SCorentin Chary break; 1829*3e230dd2SCorentin Chary case VNC_MSG_CLIENT_SET_ENCODINGS: 1830*3e230dd2SCorentin Chary if (len == 1) 1831*3e230dd2SCorentin Chary return 4; 1832*3e230dd2SCorentin Chary 1833*3e230dd2SCorentin Chary if (len == 4) { 1834*3e230dd2SCorentin Chary limit = read_u16(data, 2); 1835*3e230dd2SCorentin Chary if (limit > 0) 1836*3e230dd2SCorentin Chary return 4 + (limit * 4); 1837*3e230dd2SCorentin Chary } else 1838*3e230dd2SCorentin Chary limit = read_u16(data, 2); 1839*3e230dd2SCorentin Chary 1840*3e230dd2SCorentin Chary for (i = 0; i < limit; i++) { 1841*3e230dd2SCorentin Chary int32_t val = read_s32(data, 4 + (i * 4)); 1842*3e230dd2SCorentin Chary memcpy(data + 4 + (i * 4), &val, sizeof(val)); 1843*3e230dd2SCorentin Chary } 1844*3e230dd2SCorentin Chary 1845*3e230dd2SCorentin Chary set_encodings(vs, (int32_t *)(data + 4), limit); 1846*3e230dd2SCorentin Chary break; 1847*3e230dd2SCorentin Chary case VNC_MSG_CLIENT_FRAMEBUFFER_UPDATE_REQUEST: 1848*3e230dd2SCorentin Chary if (len == 1) 1849*3e230dd2SCorentin Chary return 10; 1850*3e230dd2SCorentin Chary 1851*3e230dd2SCorentin Chary framebuffer_update_request(vs, 1852*3e230dd2SCorentin Chary read_u8(data, 1), read_u16(data, 2), read_u16(data, 4), 1853*3e230dd2SCorentin Chary read_u16(data, 6), read_u16(data, 8)); 1854*3e230dd2SCorentin Chary break; 1855*3e230dd2SCorentin Chary case VNC_MSG_CLIENT_KEY_EVENT: 1856*3e230dd2SCorentin Chary if (len == 1) 1857*3e230dd2SCorentin Chary return 8; 1858*3e230dd2SCorentin Chary 1859*3e230dd2SCorentin Chary key_event(vs, read_u8(data, 1), read_u32(data, 4)); 1860*3e230dd2SCorentin Chary break; 1861*3e230dd2SCorentin Chary case VNC_MSG_CLIENT_POINTER_EVENT: 1862*3e230dd2SCorentin Chary if (len == 1) 1863*3e230dd2SCorentin Chary return 6; 1864*3e230dd2SCorentin Chary 1865*3e230dd2SCorentin Chary pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4)); 1866*3e230dd2SCorentin Chary break; 1867*3e230dd2SCorentin Chary case VNC_MSG_CLIENT_CUT_TEXT: 1868*3e230dd2SCorentin Chary if (len == 1) 1869*3e230dd2SCorentin Chary return 8; 1870*3e230dd2SCorentin Chary 1871*3e230dd2SCorentin Chary if (len == 8) { 1872*3e230dd2SCorentin Chary uint32_t dlen = read_u32(data, 4); 1873*3e230dd2SCorentin Chary if (dlen > 0) 1874*3e230dd2SCorentin Chary return 8 + dlen; 1875*3e230dd2SCorentin Chary } 1876*3e230dd2SCorentin Chary 1877*3e230dd2SCorentin Chary client_cut_text(vs, read_u32(data, 4), data + 8); 1878*3e230dd2SCorentin Chary break; 1879*3e230dd2SCorentin Chary case VNC_MSG_CLIENT_QEMU: 1880*3e230dd2SCorentin Chary if (len == 1) 1881*3e230dd2SCorentin Chary return 2; 1882*3e230dd2SCorentin Chary 1883*3e230dd2SCorentin Chary switch (read_u8(data, 1)) { 1884*3e230dd2SCorentin Chary case VNC_MSG_CLIENT_QEMU_EXT_KEY_EVENT: 1885*3e230dd2SCorentin Chary if (len == 2) 1886*3e230dd2SCorentin Chary return 12; 1887*3e230dd2SCorentin Chary 1888*3e230dd2SCorentin Chary ext_key_event(vs, read_u16(data, 2), 1889*3e230dd2SCorentin Chary read_u32(data, 4), read_u32(data, 8)); 1890*3e230dd2SCorentin Chary break; 1891*3e230dd2SCorentin Chary case VNC_MSG_CLIENT_QEMU_AUDIO: 1892*3e230dd2SCorentin Chary if (len == 2) 1893*3e230dd2SCorentin Chary return 4; 1894*3e230dd2SCorentin Chary 1895*3e230dd2SCorentin Chary switch (read_u16 (data, 2)) { 1896*3e230dd2SCorentin Chary case VNC_MSG_CLIENT_QEMU_AUDIO_ENABLE: 1897*3e230dd2SCorentin Chary audio_add(vs); 1898*3e230dd2SCorentin Chary break; 1899*3e230dd2SCorentin Chary case VNC_MSG_CLIENT_QEMU_AUDIO_DISABLE: 1900*3e230dd2SCorentin Chary audio_del(vs); 1901*3e230dd2SCorentin Chary break; 1902*3e230dd2SCorentin Chary case VNC_MSG_CLIENT_QEMU_AUDIO_SET_FORMAT: 1903*3e230dd2SCorentin Chary if (len == 4) 1904*3e230dd2SCorentin Chary return 10; 1905*3e230dd2SCorentin Chary switch (read_u8(data, 4)) { 1906*3e230dd2SCorentin Chary case 0: vs->as.fmt = AUD_FMT_U8; break; 1907*3e230dd2SCorentin Chary case 1: vs->as.fmt = AUD_FMT_S8; break; 1908*3e230dd2SCorentin Chary case 2: vs->as.fmt = AUD_FMT_U16; break; 1909*3e230dd2SCorentin Chary case 3: vs->as.fmt = AUD_FMT_S16; break; 1910*3e230dd2SCorentin Chary case 4: vs->as.fmt = AUD_FMT_U32; break; 1911*3e230dd2SCorentin Chary case 5: vs->as.fmt = AUD_FMT_S32; break; 1912*3e230dd2SCorentin Chary default: 1913*3e230dd2SCorentin Chary printf("Invalid audio format %d\n", read_u8(data, 4)); 1914*3e230dd2SCorentin Chary vnc_client_error(vs); 1915*3e230dd2SCorentin Chary break; 1916*3e230dd2SCorentin Chary } 1917*3e230dd2SCorentin Chary vs->as.nchannels = read_u8(data, 5); 1918*3e230dd2SCorentin Chary if (vs->as.nchannels != 1 && vs->as.nchannels != 2) { 1919*3e230dd2SCorentin Chary printf("Invalid audio channel coount %d\n", 1920*3e230dd2SCorentin Chary read_u8(data, 5)); 1921*3e230dd2SCorentin Chary vnc_client_error(vs); 1922*3e230dd2SCorentin Chary break; 1923*3e230dd2SCorentin Chary } 1924*3e230dd2SCorentin Chary vs->as.freq = read_u32(data, 6); 1925*3e230dd2SCorentin Chary break; 1926*3e230dd2SCorentin Chary default: 1927*3e230dd2SCorentin Chary printf ("Invalid audio message %d\n", read_u8(data, 4)); 1928*3e230dd2SCorentin Chary vnc_client_error(vs); 1929*3e230dd2SCorentin Chary break; 1930*3e230dd2SCorentin Chary } 1931*3e230dd2SCorentin Chary break; 1932*3e230dd2SCorentin Chary 1933*3e230dd2SCorentin Chary default: 1934*3e230dd2SCorentin Chary printf("Msg: %d\n", read_u16(data, 0)); 1935*3e230dd2SCorentin Chary vnc_client_error(vs); 1936*3e230dd2SCorentin Chary break; 1937*3e230dd2SCorentin Chary } 1938*3e230dd2SCorentin Chary break; 1939*3e230dd2SCorentin Chary default: 1940*3e230dd2SCorentin Chary printf("Msg: %d\n", data[0]); 1941*3e230dd2SCorentin Chary vnc_client_error(vs); 1942*3e230dd2SCorentin Chary break; 1943*3e230dd2SCorentin Chary } 1944*3e230dd2SCorentin Chary 1945*3e230dd2SCorentin Chary vnc_read_when(vs, protocol_client_msg, 1); 1946*3e230dd2SCorentin Chary return 0; 1947*3e230dd2SCorentin Chary } 1948*3e230dd2SCorentin Chary 1949*3e230dd2SCorentin Chary static int protocol_client_init(VncState *vs, uint8_t *data, size_t len) 1950*3e230dd2SCorentin Chary { 1951*3e230dd2SCorentin Chary char buf[1024]; 1952*3e230dd2SCorentin Chary int size; 1953*3e230dd2SCorentin Chary 1954*3e230dd2SCorentin Chary vs->client_width = ds_get_width(vs->ds); 1955*3e230dd2SCorentin Chary vs->client_height = ds_get_height(vs->ds); 1956*3e230dd2SCorentin Chary vnc_write_u16(vs, vs->client_width); 1957*3e230dd2SCorentin Chary vnc_write_u16(vs, vs->client_height); 1958*3e230dd2SCorentin Chary 1959*3e230dd2SCorentin Chary pixel_format_message(vs); 1960*3e230dd2SCorentin Chary 1961*3e230dd2SCorentin Chary if (qemu_name) 1962*3e230dd2SCorentin Chary size = snprintf(buf, sizeof(buf), "QEMU (%s)", qemu_name); 1963*3e230dd2SCorentin Chary else 1964*3e230dd2SCorentin Chary size = snprintf(buf, sizeof(buf), "QEMU"); 1965*3e230dd2SCorentin Chary 1966*3e230dd2SCorentin Chary vnc_write_u32(vs, size); 1967*3e230dd2SCorentin Chary vnc_write(vs, buf, size); 1968*3e230dd2SCorentin Chary vnc_flush(vs); 1969*3e230dd2SCorentin Chary 1970*3e230dd2SCorentin Chary vnc_client_cache_auth(vs); 1971*3e230dd2SCorentin Chary vnc_qmp_event(vs, QEVENT_VNC_INITIALIZED); 1972*3e230dd2SCorentin Chary 1973*3e230dd2SCorentin Chary vnc_read_when(vs, protocol_client_msg, 1); 1974*3e230dd2SCorentin Chary 1975*3e230dd2SCorentin Chary return 0; 1976*3e230dd2SCorentin Chary } 1977*3e230dd2SCorentin Chary 1978*3e230dd2SCorentin Chary void start_client_init(VncState *vs) 1979*3e230dd2SCorentin Chary { 1980*3e230dd2SCorentin Chary vnc_read_when(vs, protocol_client_init, 1); 1981*3e230dd2SCorentin Chary } 1982*3e230dd2SCorentin Chary 1983*3e230dd2SCorentin Chary static void make_challenge(VncState *vs) 1984*3e230dd2SCorentin Chary { 1985*3e230dd2SCorentin Chary int i; 1986*3e230dd2SCorentin Chary 1987*3e230dd2SCorentin Chary srand(time(NULL)+getpid()+getpid()*987654+rand()); 1988*3e230dd2SCorentin Chary 1989*3e230dd2SCorentin Chary for (i = 0 ; i < sizeof(vs->challenge) ; i++) 1990*3e230dd2SCorentin Chary vs->challenge[i] = (int) (256.0*rand()/(RAND_MAX+1.0)); 1991*3e230dd2SCorentin Chary } 1992*3e230dd2SCorentin Chary 1993*3e230dd2SCorentin Chary static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len) 1994*3e230dd2SCorentin Chary { 1995*3e230dd2SCorentin Chary unsigned char response[VNC_AUTH_CHALLENGE_SIZE]; 1996*3e230dd2SCorentin Chary int i, j, pwlen; 1997*3e230dd2SCorentin Chary unsigned char key[8]; 1998*3e230dd2SCorentin Chary 1999*3e230dd2SCorentin Chary if (!vs->vd->password || !vs->vd->password[0]) { 2000*3e230dd2SCorentin Chary VNC_DEBUG("No password configured on server"); 2001*3e230dd2SCorentin Chary vnc_write_u32(vs, 1); /* Reject auth */ 2002*3e230dd2SCorentin Chary if (vs->minor >= 8) { 2003*3e230dd2SCorentin Chary static const char err[] = "Authentication failed"; 2004*3e230dd2SCorentin Chary vnc_write_u32(vs, sizeof(err)); 2005*3e230dd2SCorentin Chary vnc_write(vs, err, sizeof(err)); 2006*3e230dd2SCorentin Chary } 2007*3e230dd2SCorentin Chary vnc_flush(vs); 2008*3e230dd2SCorentin Chary vnc_client_error(vs); 2009*3e230dd2SCorentin Chary return 0; 2010*3e230dd2SCorentin Chary } 2011*3e230dd2SCorentin Chary 2012*3e230dd2SCorentin Chary memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE); 2013*3e230dd2SCorentin Chary 2014*3e230dd2SCorentin Chary /* Calculate the expected challenge response */ 2015*3e230dd2SCorentin Chary pwlen = strlen(vs->vd->password); 2016*3e230dd2SCorentin Chary for (i=0; i<sizeof(key); i++) 2017*3e230dd2SCorentin Chary key[i] = i<pwlen ? vs->vd->password[i] : 0; 2018*3e230dd2SCorentin Chary deskey(key, EN0); 2019*3e230dd2SCorentin Chary for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8) 2020*3e230dd2SCorentin Chary des(response+j, response+j); 2021*3e230dd2SCorentin Chary 2022*3e230dd2SCorentin Chary /* Compare expected vs actual challenge response */ 2023*3e230dd2SCorentin Chary if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) { 2024*3e230dd2SCorentin Chary VNC_DEBUG("Client challenge reponse did not match\n"); 2025*3e230dd2SCorentin Chary vnc_write_u32(vs, 1); /* Reject auth */ 2026*3e230dd2SCorentin Chary if (vs->minor >= 8) { 2027*3e230dd2SCorentin Chary static const char err[] = "Authentication failed"; 2028*3e230dd2SCorentin Chary vnc_write_u32(vs, sizeof(err)); 2029*3e230dd2SCorentin Chary vnc_write(vs, err, sizeof(err)); 2030*3e230dd2SCorentin Chary } 2031*3e230dd2SCorentin Chary vnc_flush(vs); 2032*3e230dd2SCorentin Chary vnc_client_error(vs); 2033*3e230dd2SCorentin Chary } else { 2034*3e230dd2SCorentin Chary VNC_DEBUG("Accepting VNC challenge response\n"); 2035*3e230dd2SCorentin Chary vnc_write_u32(vs, 0); /* Accept auth */ 2036*3e230dd2SCorentin Chary vnc_flush(vs); 2037*3e230dd2SCorentin Chary 2038*3e230dd2SCorentin Chary start_client_init(vs); 2039*3e230dd2SCorentin Chary } 2040*3e230dd2SCorentin Chary return 0; 2041*3e230dd2SCorentin Chary } 2042*3e230dd2SCorentin Chary 2043*3e230dd2SCorentin Chary void start_auth_vnc(VncState *vs) 2044*3e230dd2SCorentin Chary { 2045*3e230dd2SCorentin Chary make_challenge(vs); 2046*3e230dd2SCorentin Chary /* Send client a 'random' challenge */ 2047*3e230dd2SCorentin Chary vnc_write(vs, vs->challenge, sizeof(vs->challenge)); 2048*3e230dd2SCorentin Chary vnc_flush(vs); 2049*3e230dd2SCorentin Chary 2050*3e230dd2SCorentin Chary vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge)); 2051*3e230dd2SCorentin Chary } 2052*3e230dd2SCorentin Chary 2053*3e230dd2SCorentin Chary 2054*3e230dd2SCorentin Chary static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len) 2055*3e230dd2SCorentin Chary { 2056*3e230dd2SCorentin Chary /* We only advertise 1 auth scheme at a time, so client 2057*3e230dd2SCorentin Chary * must pick the one we sent. Verify this */ 2058*3e230dd2SCorentin Chary if (data[0] != vs->vd->auth) { /* Reject auth */ 2059*3e230dd2SCorentin Chary VNC_DEBUG("Reject auth %d because it didn't match advertized\n", (int)data[0]); 2060*3e230dd2SCorentin Chary vnc_write_u32(vs, 1); 2061*3e230dd2SCorentin Chary if (vs->minor >= 8) { 2062*3e230dd2SCorentin Chary static const char err[] = "Authentication failed"; 2063*3e230dd2SCorentin Chary vnc_write_u32(vs, sizeof(err)); 2064*3e230dd2SCorentin Chary vnc_write(vs, err, sizeof(err)); 2065*3e230dd2SCorentin Chary } 2066*3e230dd2SCorentin Chary vnc_client_error(vs); 2067*3e230dd2SCorentin Chary } else { /* Accept requested auth */ 2068*3e230dd2SCorentin Chary VNC_DEBUG("Client requested auth %d\n", (int)data[0]); 2069*3e230dd2SCorentin Chary switch (vs->vd->auth) { 2070*3e230dd2SCorentin Chary case VNC_AUTH_NONE: 2071*3e230dd2SCorentin Chary VNC_DEBUG("Accept auth none\n"); 2072*3e230dd2SCorentin Chary if (vs->minor >= 8) { 2073*3e230dd2SCorentin Chary vnc_write_u32(vs, 0); /* Accept auth completion */ 2074*3e230dd2SCorentin Chary vnc_flush(vs); 2075*3e230dd2SCorentin Chary } 2076*3e230dd2SCorentin Chary start_client_init(vs); 2077*3e230dd2SCorentin Chary break; 2078*3e230dd2SCorentin Chary 2079*3e230dd2SCorentin Chary case VNC_AUTH_VNC: 2080*3e230dd2SCorentin Chary VNC_DEBUG("Start VNC auth\n"); 2081*3e230dd2SCorentin Chary start_auth_vnc(vs); 2082*3e230dd2SCorentin Chary break; 2083*3e230dd2SCorentin Chary 2084*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 2085*3e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT: 2086*3e230dd2SCorentin Chary VNC_DEBUG("Accept VeNCrypt auth\n");; 2087*3e230dd2SCorentin Chary start_auth_vencrypt(vs); 2088*3e230dd2SCorentin Chary break; 2089*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_TLS */ 2090*3e230dd2SCorentin Chary 2091*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL 2092*3e230dd2SCorentin Chary case VNC_AUTH_SASL: 2093*3e230dd2SCorentin Chary VNC_DEBUG("Accept SASL auth\n"); 2094*3e230dd2SCorentin Chary start_auth_sasl(vs); 2095*3e230dd2SCorentin Chary break; 2096*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_SASL */ 2097*3e230dd2SCorentin Chary 2098*3e230dd2SCorentin Chary default: /* Should not be possible, but just in case */ 2099*3e230dd2SCorentin Chary VNC_DEBUG("Reject auth %d server code bug\n", vs->vd->auth); 2100*3e230dd2SCorentin Chary vnc_write_u8(vs, 1); 2101*3e230dd2SCorentin Chary if (vs->minor >= 8) { 2102*3e230dd2SCorentin Chary static const char err[] = "Authentication failed"; 2103*3e230dd2SCorentin Chary vnc_write_u32(vs, sizeof(err)); 2104*3e230dd2SCorentin Chary vnc_write(vs, err, sizeof(err)); 2105*3e230dd2SCorentin Chary } 2106*3e230dd2SCorentin Chary vnc_client_error(vs); 2107*3e230dd2SCorentin Chary } 2108*3e230dd2SCorentin Chary } 2109*3e230dd2SCorentin Chary return 0; 2110*3e230dd2SCorentin Chary } 2111*3e230dd2SCorentin Chary 2112*3e230dd2SCorentin Chary static int protocol_version(VncState *vs, uint8_t *version, size_t len) 2113*3e230dd2SCorentin Chary { 2114*3e230dd2SCorentin Chary char local[13]; 2115*3e230dd2SCorentin Chary 2116*3e230dd2SCorentin Chary memcpy(local, version, 12); 2117*3e230dd2SCorentin Chary local[12] = 0; 2118*3e230dd2SCorentin Chary 2119*3e230dd2SCorentin Chary if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) { 2120*3e230dd2SCorentin Chary VNC_DEBUG("Malformed protocol version %s\n", local); 2121*3e230dd2SCorentin Chary vnc_client_error(vs); 2122*3e230dd2SCorentin Chary return 0; 2123*3e230dd2SCorentin Chary } 2124*3e230dd2SCorentin Chary VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor); 2125*3e230dd2SCorentin Chary if (vs->major != 3 || 2126*3e230dd2SCorentin Chary (vs->minor != 3 && 2127*3e230dd2SCorentin Chary vs->minor != 4 && 2128*3e230dd2SCorentin Chary vs->minor != 5 && 2129*3e230dd2SCorentin Chary vs->minor != 7 && 2130*3e230dd2SCorentin Chary vs->minor != 8)) { 2131*3e230dd2SCorentin Chary VNC_DEBUG("Unsupported client version\n"); 2132*3e230dd2SCorentin Chary vnc_write_u32(vs, VNC_AUTH_INVALID); 2133*3e230dd2SCorentin Chary vnc_flush(vs); 2134*3e230dd2SCorentin Chary vnc_client_error(vs); 2135*3e230dd2SCorentin Chary return 0; 2136*3e230dd2SCorentin Chary } 2137*3e230dd2SCorentin Chary /* Some broken clients report v3.4 or v3.5, which spec requires to be treated 2138*3e230dd2SCorentin Chary * as equivalent to v3.3 by servers 2139*3e230dd2SCorentin Chary */ 2140*3e230dd2SCorentin Chary if (vs->minor == 4 || vs->minor == 5) 2141*3e230dd2SCorentin Chary vs->minor = 3; 2142*3e230dd2SCorentin Chary 2143*3e230dd2SCorentin Chary if (vs->minor == 3) { 2144*3e230dd2SCorentin Chary if (vs->vd->auth == VNC_AUTH_NONE) { 2145*3e230dd2SCorentin Chary VNC_DEBUG("Tell client auth none\n"); 2146*3e230dd2SCorentin Chary vnc_write_u32(vs, vs->vd->auth); 2147*3e230dd2SCorentin Chary vnc_flush(vs); 2148*3e230dd2SCorentin Chary start_client_init(vs); 2149*3e230dd2SCorentin Chary } else if (vs->vd->auth == VNC_AUTH_VNC) { 2150*3e230dd2SCorentin Chary VNC_DEBUG("Tell client VNC auth\n"); 2151*3e230dd2SCorentin Chary vnc_write_u32(vs, vs->vd->auth); 2152*3e230dd2SCorentin Chary vnc_flush(vs); 2153*3e230dd2SCorentin Chary start_auth_vnc(vs); 2154*3e230dd2SCorentin Chary } else { 2155*3e230dd2SCorentin Chary VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->vd->auth); 2156*3e230dd2SCorentin Chary vnc_write_u32(vs, VNC_AUTH_INVALID); 2157*3e230dd2SCorentin Chary vnc_flush(vs); 2158*3e230dd2SCorentin Chary vnc_client_error(vs); 2159*3e230dd2SCorentin Chary } 2160*3e230dd2SCorentin Chary } else { 2161*3e230dd2SCorentin Chary VNC_DEBUG("Telling client we support auth %d\n", vs->vd->auth); 2162*3e230dd2SCorentin Chary vnc_write_u8(vs, 1); /* num auth */ 2163*3e230dd2SCorentin Chary vnc_write_u8(vs, vs->vd->auth); 2164*3e230dd2SCorentin Chary vnc_read_when(vs, protocol_client_auth, 1); 2165*3e230dd2SCorentin Chary vnc_flush(vs); 2166*3e230dd2SCorentin Chary } 2167*3e230dd2SCorentin Chary 2168*3e230dd2SCorentin Chary return 0; 2169*3e230dd2SCorentin Chary } 2170*3e230dd2SCorentin Chary 2171*3e230dd2SCorentin Chary static int vnc_refresh_server_surface(VncDisplay *vd) 2172*3e230dd2SCorentin Chary { 2173*3e230dd2SCorentin Chary int y; 2174*3e230dd2SCorentin Chary uint8_t *guest_row; 2175*3e230dd2SCorentin Chary uint8_t *server_row; 2176*3e230dd2SCorentin Chary int cmp_bytes; 2177*3e230dd2SCorentin Chary uint32_t width_mask[VNC_DIRTY_WORDS]; 2178*3e230dd2SCorentin Chary VncState *vs; 2179*3e230dd2SCorentin Chary int has_dirty = 0; 2180*3e230dd2SCorentin Chary 2181*3e230dd2SCorentin Chary /* 2182*3e230dd2SCorentin Chary * Walk through the guest dirty map. 2183*3e230dd2SCorentin Chary * Check and copy modified bits from guest to server surface. 2184*3e230dd2SCorentin Chary * Update server dirty map. 2185*3e230dd2SCorentin Chary */ 2186*3e230dd2SCorentin Chary vnc_set_bits(width_mask, (ds_get_width(vd->ds) / 16), VNC_DIRTY_WORDS); 2187*3e230dd2SCorentin Chary cmp_bytes = 16 * ds_get_bytes_per_pixel(vd->ds); 2188*3e230dd2SCorentin Chary guest_row = vd->guest.ds->data; 2189*3e230dd2SCorentin Chary server_row = vd->server->data; 2190*3e230dd2SCorentin Chary for (y = 0; y < vd->guest.ds->height; y++) { 2191*3e230dd2SCorentin Chary if (vnc_and_bits(vd->guest.dirty[y], width_mask, VNC_DIRTY_WORDS)) { 2192*3e230dd2SCorentin Chary int x; 2193*3e230dd2SCorentin Chary uint8_t *guest_ptr; 2194*3e230dd2SCorentin Chary uint8_t *server_ptr; 2195*3e230dd2SCorentin Chary 2196*3e230dd2SCorentin Chary guest_ptr = guest_row; 2197*3e230dd2SCorentin Chary server_ptr = server_row; 2198*3e230dd2SCorentin Chary 2199*3e230dd2SCorentin Chary for (x = 0; x < vd->guest.ds->width; 2200*3e230dd2SCorentin Chary x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) { 2201*3e230dd2SCorentin Chary if (!vnc_get_bit(vd->guest.dirty[y], (x / 16))) 2202*3e230dd2SCorentin Chary continue; 2203*3e230dd2SCorentin Chary vnc_clear_bit(vd->guest.dirty[y], (x / 16)); 2204*3e230dd2SCorentin Chary if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0) 2205*3e230dd2SCorentin Chary continue; 2206*3e230dd2SCorentin Chary memcpy(server_ptr, guest_ptr, cmp_bytes); 2207*3e230dd2SCorentin Chary QTAILQ_FOREACH(vs, &vd->clients, next) { 2208*3e230dd2SCorentin Chary vnc_set_bit(vs->dirty[y], (x / 16)); 2209*3e230dd2SCorentin Chary } 2210*3e230dd2SCorentin Chary has_dirty++; 2211*3e230dd2SCorentin Chary } 2212*3e230dd2SCorentin Chary } 2213*3e230dd2SCorentin Chary guest_row += ds_get_linesize(vd->ds); 2214*3e230dd2SCorentin Chary server_row += ds_get_linesize(vd->ds); 2215*3e230dd2SCorentin Chary } 2216*3e230dd2SCorentin Chary return has_dirty; 2217*3e230dd2SCorentin Chary } 2218*3e230dd2SCorentin Chary 2219*3e230dd2SCorentin Chary static void vnc_refresh(void *opaque) 2220*3e230dd2SCorentin Chary { 2221*3e230dd2SCorentin Chary VncDisplay *vd = opaque; 2222*3e230dd2SCorentin Chary VncState *vs, *vn; 2223*3e230dd2SCorentin Chary int has_dirty, rects = 0; 2224*3e230dd2SCorentin Chary 2225*3e230dd2SCorentin Chary vga_hw_update(); 2226*3e230dd2SCorentin Chary 2227*3e230dd2SCorentin Chary has_dirty = vnc_refresh_server_surface(vd); 2228*3e230dd2SCorentin Chary 2229*3e230dd2SCorentin Chary QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) { 2230*3e230dd2SCorentin Chary rects += vnc_update_client(vs, has_dirty); 2231*3e230dd2SCorentin Chary /* vs might be free()ed here */ 2232*3e230dd2SCorentin Chary } 2233*3e230dd2SCorentin Chary /* vd->timer could be NULL now if the last client disconnected, 2234*3e230dd2SCorentin Chary * in this case don't update the timer */ 2235*3e230dd2SCorentin Chary if (vd->timer == NULL) 2236*3e230dd2SCorentin Chary return; 2237*3e230dd2SCorentin Chary 2238*3e230dd2SCorentin Chary if (has_dirty && rects) { 2239*3e230dd2SCorentin Chary vd->timer_interval /= 2; 2240*3e230dd2SCorentin Chary if (vd->timer_interval < VNC_REFRESH_INTERVAL_BASE) 2241*3e230dd2SCorentin Chary vd->timer_interval = VNC_REFRESH_INTERVAL_BASE; 2242*3e230dd2SCorentin Chary } else { 2243*3e230dd2SCorentin Chary vd->timer_interval += VNC_REFRESH_INTERVAL_INC; 2244*3e230dd2SCorentin Chary if (vd->timer_interval > VNC_REFRESH_INTERVAL_MAX) 2245*3e230dd2SCorentin Chary vd->timer_interval = VNC_REFRESH_INTERVAL_MAX; 2246*3e230dd2SCorentin Chary } 2247*3e230dd2SCorentin Chary qemu_mod_timer(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval); 2248*3e230dd2SCorentin Chary } 2249*3e230dd2SCorentin Chary 2250*3e230dd2SCorentin Chary static void vnc_init_timer(VncDisplay *vd) 2251*3e230dd2SCorentin Chary { 2252*3e230dd2SCorentin Chary vd->timer_interval = VNC_REFRESH_INTERVAL_BASE; 2253*3e230dd2SCorentin Chary if (vd->timer == NULL && !QTAILQ_EMPTY(&vd->clients)) { 2254*3e230dd2SCorentin Chary vd->timer = qemu_new_timer(rt_clock, vnc_refresh, vd); 2255*3e230dd2SCorentin Chary vnc_refresh(vd); 2256*3e230dd2SCorentin Chary } 2257*3e230dd2SCorentin Chary } 2258*3e230dd2SCorentin Chary 2259*3e230dd2SCorentin Chary static void vnc_remove_timer(VncDisplay *vd) 2260*3e230dd2SCorentin Chary { 2261*3e230dd2SCorentin Chary if (vd->timer != NULL && QTAILQ_EMPTY(&vd->clients)) { 2262*3e230dd2SCorentin Chary qemu_del_timer(vd->timer); 2263*3e230dd2SCorentin Chary qemu_free_timer(vd->timer); 2264*3e230dd2SCorentin Chary vd->timer = NULL; 2265*3e230dd2SCorentin Chary } 2266*3e230dd2SCorentin Chary } 2267*3e230dd2SCorentin Chary 2268*3e230dd2SCorentin Chary static void vnc_connect(VncDisplay *vd, int csock) 2269*3e230dd2SCorentin Chary { 2270*3e230dd2SCorentin Chary VncState *vs = qemu_mallocz(sizeof(VncState)); 2271*3e230dd2SCorentin Chary vs->csock = csock; 2272*3e230dd2SCorentin Chary 2273*3e230dd2SCorentin Chary VNC_DEBUG("New client on socket %d\n", csock); 2274*3e230dd2SCorentin Chary dcl->idle = 0; 2275*3e230dd2SCorentin Chary socket_set_nonblock(vs->csock); 2276*3e230dd2SCorentin Chary qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs); 2277*3e230dd2SCorentin Chary 2278*3e230dd2SCorentin Chary vnc_client_cache_addr(vs); 2279*3e230dd2SCorentin Chary vnc_qmp_event(vs, QEVENT_VNC_CONNECTED); 2280*3e230dd2SCorentin Chary 2281*3e230dd2SCorentin Chary vs->vd = vd; 2282*3e230dd2SCorentin Chary vs->ds = vd->ds; 2283*3e230dd2SCorentin Chary vs->last_x = -1; 2284*3e230dd2SCorentin Chary vs->last_y = -1; 2285*3e230dd2SCorentin Chary 2286*3e230dd2SCorentin Chary vs->as.freq = 44100; 2287*3e230dd2SCorentin Chary vs->as.nchannels = 2; 2288*3e230dd2SCorentin Chary vs->as.fmt = AUD_FMT_S16; 2289*3e230dd2SCorentin Chary vs->as.endianness = 0; 2290*3e230dd2SCorentin Chary 2291*3e230dd2SCorentin Chary QTAILQ_INSERT_HEAD(&vd->clients, vs, next); 2292*3e230dd2SCorentin Chary 2293*3e230dd2SCorentin Chary vga_hw_update(); 2294*3e230dd2SCorentin Chary 2295*3e230dd2SCorentin Chary vnc_write(vs, "RFB 003.008\n", 12); 2296*3e230dd2SCorentin Chary vnc_flush(vs); 2297*3e230dd2SCorentin Chary vnc_read_when(vs, protocol_version, 12); 2298*3e230dd2SCorentin Chary reset_keys(vs); 2299*3e230dd2SCorentin Chary if (vs->vd->lock_key_sync) 2300*3e230dd2SCorentin Chary vs->led = qemu_add_led_event_handler(kbd_leds, vs); 2301*3e230dd2SCorentin Chary 2302*3e230dd2SCorentin Chary vs->mouse_mode_notifier.notify = check_pointer_type_change; 2303*3e230dd2SCorentin Chary qemu_add_mouse_mode_change_notifier(&vs->mouse_mode_notifier); 2304*3e230dd2SCorentin Chary 2305*3e230dd2SCorentin Chary vnc_init_timer(vd); 2306*3e230dd2SCorentin Chary 2307*3e230dd2SCorentin Chary /* vs might be free()ed here */ 2308*3e230dd2SCorentin Chary } 2309*3e230dd2SCorentin Chary 2310*3e230dd2SCorentin Chary static void vnc_listen_read(void *opaque) 2311*3e230dd2SCorentin Chary { 2312*3e230dd2SCorentin Chary VncDisplay *vs = opaque; 2313*3e230dd2SCorentin Chary struct sockaddr_in addr; 2314*3e230dd2SCorentin Chary socklen_t addrlen = sizeof(addr); 2315*3e230dd2SCorentin Chary 2316*3e230dd2SCorentin Chary /* Catch-up */ 2317*3e230dd2SCorentin Chary vga_hw_update(); 2318*3e230dd2SCorentin Chary 2319*3e230dd2SCorentin Chary int csock = qemu_accept(vs->lsock, (struct sockaddr *)&addr, &addrlen); 2320*3e230dd2SCorentin Chary if (csock != -1) { 2321*3e230dd2SCorentin Chary vnc_connect(vs, csock); 2322*3e230dd2SCorentin Chary } 2323*3e230dd2SCorentin Chary } 2324*3e230dd2SCorentin Chary 2325*3e230dd2SCorentin Chary void vnc_display_init(DisplayState *ds) 2326*3e230dd2SCorentin Chary { 2327*3e230dd2SCorentin Chary VncDisplay *vs = qemu_mallocz(sizeof(*vs)); 2328*3e230dd2SCorentin Chary 2329*3e230dd2SCorentin Chary dcl = qemu_mallocz(sizeof(DisplayChangeListener)); 2330*3e230dd2SCorentin Chary 2331*3e230dd2SCorentin Chary ds->opaque = vs; 2332*3e230dd2SCorentin Chary dcl->idle = 1; 2333*3e230dd2SCorentin Chary vnc_display = vs; 2334*3e230dd2SCorentin Chary 2335*3e230dd2SCorentin Chary vs->lsock = -1; 2336*3e230dd2SCorentin Chary 2337*3e230dd2SCorentin Chary vs->ds = ds; 2338*3e230dd2SCorentin Chary QTAILQ_INIT(&vs->clients); 2339*3e230dd2SCorentin Chary 2340*3e230dd2SCorentin Chary if (keyboard_layout) 2341*3e230dd2SCorentin Chary vs->kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout); 2342*3e230dd2SCorentin Chary else 2343*3e230dd2SCorentin Chary vs->kbd_layout = init_keyboard_layout(name2keysym, "en-us"); 2344*3e230dd2SCorentin Chary 2345*3e230dd2SCorentin Chary if (!vs->kbd_layout) 2346*3e230dd2SCorentin Chary exit(1); 2347*3e230dd2SCorentin Chary 2348*3e230dd2SCorentin Chary dcl->dpy_copy = vnc_dpy_copy; 2349*3e230dd2SCorentin Chary dcl->dpy_update = vnc_dpy_update; 2350*3e230dd2SCorentin Chary dcl->dpy_resize = vnc_dpy_resize; 2351*3e230dd2SCorentin Chary dcl->dpy_setdata = vnc_dpy_setdata; 2352*3e230dd2SCorentin Chary register_displaychangelistener(ds, dcl); 2353*3e230dd2SCorentin Chary ds->mouse_set = vnc_mouse_set; 2354*3e230dd2SCorentin Chary ds->cursor_define = vnc_dpy_cursor_define; 2355*3e230dd2SCorentin Chary } 2356*3e230dd2SCorentin Chary 2357*3e230dd2SCorentin Chary 2358*3e230dd2SCorentin Chary void vnc_display_close(DisplayState *ds) 2359*3e230dd2SCorentin Chary { 2360*3e230dd2SCorentin Chary VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; 2361*3e230dd2SCorentin Chary 2362*3e230dd2SCorentin Chary if (!vs) 2363*3e230dd2SCorentin Chary return; 2364*3e230dd2SCorentin Chary if (vs->display) { 2365*3e230dd2SCorentin Chary qemu_free(vs->display); 2366*3e230dd2SCorentin Chary vs->display = NULL; 2367*3e230dd2SCorentin Chary } 2368*3e230dd2SCorentin Chary if (vs->lsock != -1) { 2369*3e230dd2SCorentin Chary qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL); 2370*3e230dd2SCorentin Chary close(vs->lsock); 2371*3e230dd2SCorentin Chary vs->lsock = -1; 2372*3e230dd2SCorentin Chary } 2373*3e230dd2SCorentin Chary vs->auth = VNC_AUTH_INVALID; 2374*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 2375*3e230dd2SCorentin Chary vs->subauth = VNC_AUTH_INVALID; 2376*3e230dd2SCorentin Chary vs->tls.x509verify = 0; 2377*3e230dd2SCorentin Chary #endif 2378*3e230dd2SCorentin Chary } 2379*3e230dd2SCorentin Chary 2380*3e230dd2SCorentin Chary int vnc_display_password(DisplayState *ds, const char *password) 2381*3e230dd2SCorentin Chary { 2382*3e230dd2SCorentin Chary VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; 2383*3e230dd2SCorentin Chary 2384*3e230dd2SCorentin Chary if (!vs) { 2385*3e230dd2SCorentin Chary return -1; 2386*3e230dd2SCorentin Chary } 2387*3e230dd2SCorentin Chary 2388*3e230dd2SCorentin Chary if (vs->password) { 2389*3e230dd2SCorentin Chary qemu_free(vs->password); 2390*3e230dd2SCorentin Chary vs->password = NULL; 2391*3e230dd2SCorentin Chary } 2392*3e230dd2SCorentin Chary if (password && password[0]) { 2393*3e230dd2SCorentin Chary if (!(vs->password = qemu_strdup(password))) 2394*3e230dd2SCorentin Chary return -1; 2395*3e230dd2SCorentin Chary if (vs->auth == VNC_AUTH_NONE) { 2396*3e230dd2SCorentin Chary vs->auth = VNC_AUTH_VNC; 2397*3e230dd2SCorentin Chary } 2398*3e230dd2SCorentin Chary } else { 2399*3e230dd2SCorentin Chary vs->auth = VNC_AUTH_NONE; 2400*3e230dd2SCorentin Chary } 2401*3e230dd2SCorentin Chary 2402*3e230dd2SCorentin Chary return 0; 2403*3e230dd2SCorentin Chary } 2404*3e230dd2SCorentin Chary 2405*3e230dd2SCorentin Chary char *vnc_display_local_addr(DisplayState *ds) 2406*3e230dd2SCorentin Chary { 2407*3e230dd2SCorentin Chary VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; 2408*3e230dd2SCorentin Chary 2409*3e230dd2SCorentin Chary return vnc_socket_local_addr("%s:%s", vs->lsock); 2410*3e230dd2SCorentin Chary } 2411*3e230dd2SCorentin Chary 2412*3e230dd2SCorentin Chary int vnc_display_open(DisplayState *ds, const char *display) 2413*3e230dd2SCorentin Chary { 2414*3e230dd2SCorentin Chary VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; 2415*3e230dd2SCorentin Chary const char *options; 2416*3e230dd2SCorentin Chary int password = 0; 2417*3e230dd2SCorentin Chary int reverse = 0; 2418*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 2419*3e230dd2SCorentin Chary int tls = 0, x509 = 0; 2420*3e230dd2SCorentin Chary #endif 2421*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL 2422*3e230dd2SCorentin Chary int sasl = 0; 2423*3e230dd2SCorentin Chary int saslErr; 2424*3e230dd2SCorentin Chary #endif 2425*3e230dd2SCorentin Chary int acl = 0; 2426*3e230dd2SCorentin Chary int lock_key_sync = 1; 2427*3e230dd2SCorentin Chary 2428*3e230dd2SCorentin Chary if (!vnc_display) 2429*3e230dd2SCorentin Chary return -1; 2430*3e230dd2SCorentin Chary vnc_display_close(ds); 2431*3e230dd2SCorentin Chary if (strcmp(display, "none") == 0) 2432*3e230dd2SCorentin Chary return 0; 2433*3e230dd2SCorentin Chary 2434*3e230dd2SCorentin Chary if (!(vs->display = strdup(display))) 2435*3e230dd2SCorentin Chary return -1; 2436*3e230dd2SCorentin Chary 2437*3e230dd2SCorentin Chary options = display; 2438*3e230dd2SCorentin Chary while ((options = strchr(options, ','))) { 2439*3e230dd2SCorentin Chary options++; 2440*3e230dd2SCorentin Chary if (strncmp(options, "password", 8) == 0) { 2441*3e230dd2SCorentin Chary password = 1; /* Require password auth */ 2442*3e230dd2SCorentin Chary } else if (strncmp(options, "reverse", 7) == 0) { 2443*3e230dd2SCorentin Chary reverse = 1; 2444*3e230dd2SCorentin Chary } else if (strncmp(options, "no-lock-key-sync", 9) == 0) { 2445*3e230dd2SCorentin Chary lock_key_sync = 0; 2446*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL 2447*3e230dd2SCorentin Chary } else if (strncmp(options, "sasl", 4) == 0) { 2448*3e230dd2SCorentin Chary sasl = 1; /* Require SASL auth */ 2449*3e230dd2SCorentin Chary #endif 2450*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 2451*3e230dd2SCorentin Chary } else if (strncmp(options, "tls", 3) == 0) { 2452*3e230dd2SCorentin Chary tls = 1; /* Require TLS */ 2453*3e230dd2SCorentin Chary } else if (strncmp(options, "x509", 4) == 0) { 2454*3e230dd2SCorentin Chary char *start, *end; 2455*3e230dd2SCorentin Chary x509 = 1; /* Require x509 certificates */ 2456*3e230dd2SCorentin Chary if (strncmp(options, "x509verify", 10) == 0) 2457*3e230dd2SCorentin Chary vs->tls.x509verify = 1; /* ...and verify client certs */ 2458*3e230dd2SCorentin Chary 2459*3e230dd2SCorentin Chary /* Now check for 'x509=/some/path' postfix 2460*3e230dd2SCorentin Chary * and use that to setup x509 certificate/key paths */ 2461*3e230dd2SCorentin Chary start = strchr(options, '='); 2462*3e230dd2SCorentin Chary end = strchr(options, ','); 2463*3e230dd2SCorentin Chary if (start && (!end || (start < end))) { 2464*3e230dd2SCorentin Chary int len = end ? end-(start+1) : strlen(start+1); 2465*3e230dd2SCorentin Chary char *path = qemu_strndup(start + 1, len); 2466*3e230dd2SCorentin Chary 2467*3e230dd2SCorentin Chary VNC_DEBUG("Trying certificate path '%s'\n", path); 2468*3e230dd2SCorentin Chary if (vnc_tls_set_x509_creds_dir(vs, path) < 0) { 2469*3e230dd2SCorentin Chary fprintf(stderr, "Failed to find x509 certificates/keys in %s\n", path); 2470*3e230dd2SCorentin Chary qemu_free(path); 2471*3e230dd2SCorentin Chary qemu_free(vs->display); 2472*3e230dd2SCorentin Chary vs->display = NULL; 2473*3e230dd2SCorentin Chary return -1; 2474*3e230dd2SCorentin Chary } 2475*3e230dd2SCorentin Chary qemu_free(path); 2476*3e230dd2SCorentin Chary } else { 2477*3e230dd2SCorentin Chary fprintf(stderr, "No certificate path provided\n"); 2478*3e230dd2SCorentin Chary qemu_free(vs->display); 2479*3e230dd2SCorentin Chary vs->display = NULL; 2480*3e230dd2SCorentin Chary return -1; 2481*3e230dd2SCorentin Chary } 2482*3e230dd2SCorentin Chary #endif 2483*3e230dd2SCorentin Chary } else if (strncmp(options, "acl", 3) == 0) { 2484*3e230dd2SCorentin Chary acl = 1; 2485*3e230dd2SCorentin Chary } else if (strncmp(options, "lossy", 5) == 0) { 2486*3e230dd2SCorentin Chary vs->lossy = true; 2487*3e230dd2SCorentin Chary } 2488*3e230dd2SCorentin Chary } 2489*3e230dd2SCorentin Chary 2490*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 2491*3e230dd2SCorentin Chary if (acl && x509 && vs->tls.x509verify) { 2492*3e230dd2SCorentin Chary if (!(vs->tls.acl = qemu_acl_init("vnc.x509dname"))) { 2493*3e230dd2SCorentin Chary fprintf(stderr, "Failed to create x509 dname ACL\n"); 2494*3e230dd2SCorentin Chary exit(1); 2495*3e230dd2SCorentin Chary } 2496*3e230dd2SCorentin Chary } 2497*3e230dd2SCorentin Chary #endif 2498*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL 2499*3e230dd2SCorentin Chary if (acl && sasl) { 2500*3e230dd2SCorentin Chary if (!(vs->sasl.acl = qemu_acl_init("vnc.username"))) { 2501*3e230dd2SCorentin Chary fprintf(stderr, "Failed to create username ACL\n"); 2502*3e230dd2SCorentin Chary exit(1); 2503*3e230dd2SCorentin Chary } 2504*3e230dd2SCorentin Chary } 2505*3e230dd2SCorentin Chary #endif 2506*3e230dd2SCorentin Chary 2507*3e230dd2SCorentin Chary /* 2508*3e230dd2SCorentin Chary * Combinations we support here: 2509*3e230dd2SCorentin Chary * 2510*3e230dd2SCorentin Chary * - no-auth (clear text, no auth) 2511*3e230dd2SCorentin Chary * - password (clear text, weak auth) 2512*3e230dd2SCorentin Chary * - sasl (encrypt, good auth *IF* using Kerberos via GSSAPI) 2513*3e230dd2SCorentin Chary * - tls (encrypt, weak anonymous creds, no auth) 2514*3e230dd2SCorentin Chary * - tls + password (encrypt, weak anonymous creds, weak auth) 2515*3e230dd2SCorentin Chary * - tls + sasl (encrypt, weak anonymous creds, good auth) 2516*3e230dd2SCorentin Chary * - tls + x509 (encrypt, good x509 creds, no auth) 2517*3e230dd2SCorentin Chary * - tls + x509 + password (encrypt, good x509 creds, weak auth) 2518*3e230dd2SCorentin Chary * - tls + x509 + sasl (encrypt, good x509 creds, good auth) 2519*3e230dd2SCorentin Chary * 2520*3e230dd2SCorentin Chary * NB1. TLS is a stackable auth scheme. 2521*3e230dd2SCorentin Chary * NB2. the x509 schemes have option to validate a client cert dname 2522*3e230dd2SCorentin Chary */ 2523*3e230dd2SCorentin Chary if (password) { 2524*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 2525*3e230dd2SCorentin Chary if (tls) { 2526*3e230dd2SCorentin Chary vs->auth = VNC_AUTH_VENCRYPT; 2527*3e230dd2SCorentin Chary if (x509) { 2528*3e230dd2SCorentin Chary VNC_DEBUG("Initializing VNC server with x509 password auth\n"); 2529*3e230dd2SCorentin Chary vs->subauth = VNC_AUTH_VENCRYPT_X509VNC; 2530*3e230dd2SCorentin Chary } else { 2531*3e230dd2SCorentin Chary VNC_DEBUG("Initializing VNC server with TLS password auth\n"); 2532*3e230dd2SCorentin Chary vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC; 2533*3e230dd2SCorentin Chary } 2534*3e230dd2SCorentin Chary } else { 2535*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_TLS */ 2536*3e230dd2SCorentin Chary VNC_DEBUG("Initializing VNC server with password auth\n"); 2537*3e230dd2SCorentin Chary vs->auth = VNC_AUTH_VNC; 2538*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 2539*3e230dd2SCorentin Chary vs->subauth = VNC_AUTH_INVALID; 2540*3e230dd2SCorentin Chary } 2541*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_TLS */ 2542*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL 2543*3e230dd2SCorentin Chary } else if (sasl) { 2544*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 2545*3e230dd2SCorentin Chary if (tls) { 2546*3e230dd2SCorentin Chary vs->auth = VNC_AUTH_VENCRYPT; 2547*3e230dd2SCorentin Chary if (x509) { 2548*3e230dd2SCorentin Chary VNC_DEBUG("Initializing VNC server with x509 SASL auth\n"); 2549*3e230dd2SCorentin Chary vs->subauth = VNC_AUTH_VENCRYPT_X509SASL; 2550*3e230dd2SCorentin Chary } else { 2551*3e230dd2SCorentin Chary VNC_DEBUG("Initializing VNC server with TLS SASL auth\n"); 2552*3e230dd2SCorentin Chary vs->subauth = VNC_AUTH_VENCRYPT_TLSSASL; 2553*3e230dd2SCorentin Chary } 2554*3e230dd2SCorentin Chary } else { 2555*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_TLS */ 2556*3e230dd2SCorentin Chary VNC_DEBUG("Initializing VNC server with SASL auth\n"); 2557*3e230dd2SCorentin Chary vs->auth = VNC_AUTH_SASL; 2558*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 2559*3e230dd2SCorentin Chary vs->subauth = VNC_AUTH_INVALID; 2560*3e230dd2SCorentin Chary } 2561*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_TLS */ 2562*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_SASL */ 2563*3e230dd2SCorentin Chary } else { 2564*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 2565*3e230dd2SCorentin Chary if (tls) { 2566*3e230dd2SCorentin Chary vs->auth = VNC_AUTH_VENCRYPT; 2567*3e230dd2SCorentin Chary if (x509) { 2568*3e230dd2SCorentin Chary VNC_DEBUG("Initializing VNC server with x509 no auth\n"); 2569*3e230dd2SCorentin Chary vs->subauth = VNC_AUTH_VENCRYPT_X509NONE; 2570*3e230dd2SCorentin Chary } else { 2571*3e230dd2SCorentin Chary VNC_DEBUG("Initializing VNC server with TLS no auth\n"); 2572*3e230dd2SCorentin Chary vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE; 2573*3e230dd2SCorentin Chary } 2574*3e230dd2SCorentin Chary } else { 2575*3e230dd2SCorentin Chary #endif 2576*3e230dd2SCorentin Chary VNC_DEBUG("Initializing VNC server with no auth\n"); 2577*3e230dd2SCorentin Chary vs->auth = VNC_AUTH_NONE; 2578*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS 2579*3e230dd2SCorentin Chary vs->subauth = VNC_AUTH_INVALID; 2580*3e230dd2SCorentin Chary } 2581*3e230dd2SCorentin Chary #endif 2582*3e230dd2SCorentin Chary } 2583*3e230dd2SCorentin Chary 2584*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL 2585*3e230dd2SCorentin Chary if ((saslErr = sasl_server_init(NULL, "qemu")) != SASL_OK) { 2586*3e230dd2SCorentin Chary fprintf(stderr, "Failed to initialize SASL auth %s", 2587*3e230dd2SCorentin Chary sasl_errstring(saslErr, NULL, NULL)); 2588*3e230dd2SCorentin Chary free(vs->display); 2589*3e230dd2SCorentin Chary vs->display = NULL; 2590*3e230dd2SCorentin Chary return -1; 2591*3e230dd2SCorentin Chary } 2592*3e230dd2SCorentin Chary #endif 2593*3e230dd2SCorentin Chary vs->lock_key_sync = lock_key_sync; 2594*3e230dd2SCorentin Chary 2595*3e230dd2SCorentin Chary if (reverse) { 2596*3e230dd2SCorentin Chary /* connect to viewer */ 2597*3e230dd2SCorentin Chary if (strncmp(display, "unix:", 5) == 0) 2598*3e230dd2SCorentin Chary vs->lsock = unix_connect(display+5); 2599*3e230dd2SCorentin Chary else 2600*3e230dd2SCorentin Chary vs->lsock = inet_connect(display, SOCK_STREAM); 2601*3e230dd2SCorentin Chary if (-1 == vs->lsock) { 2602*3e230dd2SCorentin Chary free(vs->display); 2603*3e230dd2SCorentin Chary vs->display = NULL; 2604*3e230dd2SCorentin Chary return -1; 2605*3e230dd2SCorentin Chary } else { 2606*3e230dd2SCorentin Chary int csock = vs->lsock; 2607*3e230dd2SCorentin Chary vs->lsock = -1; 2608*3e230dd2SCorentin Chary vnc_connect(vs, csock); 2609*3e230dd2SCorentin Chary } 2610*3e230dd2SCorentin Chary return 0; 2611*3e230dd2SCorentin Chary 2612*3e230dd2SCorentin Chary } else { 2613*3e230dd2SCorentin Chary /* listen for connects */ 2614*3e230dd2SCorentin Chary char *dpy; 2615*3e230dd2SCorentin Chary dpy = qemu_malloc(256); 2616*3e230dd2SCorentin Chary if (strncmp(display, "unix:", 5) == 0) { 2617*3e230dd2SCorentin Chary pstrcpy(dpy, 256, "unix:"); 2618*3e230dd2SCorentin Chary vs->lsock = unix_listen(display+5, dpy+5, 256-5); 2619*3e230dd2SCorentin Chary } else { 2620*3e230dd2SCorentin Chary vs->lsock = inet_listen(display, dpy, 256, SOCK_STREAM, 5900); 2621*3e230dd2SCorentin Chary } 2622*3e230dd2SCorentin Chary if (-1 == vs->lsock) { 2623*3e230dd2SCorentin Chary free(dpy); 2624*3e230dd2SCorentin Chary return -1; 2625*3e230dd2SCorentin Chary } else { 2626*3e230dd2SCorentin Chary free(vs->display); 2627*3e230dd2SCorentin Chary vs->display = dpy; 2628*3e230dd2SCorentin Chary } 2629*3e230dd2SCorentin Chary } 2630*3e230dd2SCorentin Chary return qemu_set_fd_handler2(vs->lsock, NULL, vnc_listen_read, NULL, vs); 2631*3e230dd2SCorentin Chary } 2632