vnc.c revision 20894ae3fa98f82da925fbeb72e616eef509758a
18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * QEMU VNC display driver 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws> 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (C) 2006 Fabrice Bellard 65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright (C) 2009 Red Hat, Inc 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the Software without restriction, including without limitation the rights 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is 138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * furnished to do so, subject to the following conditions: 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The above copyright notice and this permission notice shall be included in 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * all copies or substantial portions of the Software. 178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE. 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "vnc.h" 288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "sysemu.h" 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu_socket.h" 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu-timer.h" 315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "acl.h" 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VNC_REFRESH_INTERVAL (1000 / 30) 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "vnc_keysym.h" 368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "d3des.h" 378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define count_bits(c, v) { \ 395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (c = 0; v; v >>= 1) \ 405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner { \ 415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner c += v & 1; \ 425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } \ 435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic VncDisplay *vnc_display; /* needed for info vnc */ 475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic DisplayChangeListener *dcl; 488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic char *addr_to_string(const char *format, 505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_storage *sa, 515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socklen_t salen) { 525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *addr; 535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char host[NI_MAXHOST]; 545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char serv[NI_MAXSERV]; 555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int err; 565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size_t addrlen; 578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((err = getnameinfo((struct sockaddr *)sa, salen, 595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner host, sizeof(host), 605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner serv, sizeof(serv), 615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NI_NUMERICHOST | NI_NUMERICSERV)) != 0) { 625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Cannot resolve address %d: %s\n", 635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner err, gai_strerror(err)); 645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Enough for the existing format + the 2 vars we're 685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * substituting in. */ 695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addrlen = strlen(format) + strlen(host) + strlen(serv); 705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr = qemu_malloc(addrlen + 1); 715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(addr, addrlen, format, host, serv); 725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr[addrlen] = '\0'; 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return addr; 755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerchar *vnc_socket_local_addr(const char *format, int fd) { 795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_storage sa; 805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socklen_t salen; 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner salen = sizeof(sa); 835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (getsockname(fd, (struct sockaddr*)&sa, &salen) < 0) 845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return addr_to_string(format, &sa, salen); 875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerchar *vnc_socket_remote_addr(const char *format, int fd) { 905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_storage sa; 915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socklen_t salen; 928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner salen = sizeof(sa); 945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (getpeername(fd, (struct sockaddr*)&sa, &salen) < 0) 955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return addr_to_string(format, &sa, salen); 985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const char *vnc_auth_name(VncDisplay *vd) { 1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (vd->auth) { 1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_INVALID: 1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "invalid"; 1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_NONE: 1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "none"; 1065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_VNC: 1075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "vnc"; 1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_RA2: 1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "ra2"; 1105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_RA2NE: 1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "ra2ne"; 1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_TIGHT: 1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "tight"; 1145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_ULTRA: 1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "ultra"; 1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_TLS: 1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "tls"; 1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_VENCRYPT: 1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_VNC_TLS 1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (vd->subauth) { 1215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_VENCRYPT_PLAIN: 1225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "vencrypt+plain"; 1235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_VENCRYPT_TLSNONE: 1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "vencrypt+tls+none"; 1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_VENCRYPT_TLSVNC: 1265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "vencrypt+tls+vnc"; 1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_VENCRYPT_TLSPLAIN: 1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "vencrypt+tls+plain"; 1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_VENCRYPT_X509NONE: 1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "vencrypt+x509+none"; 1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_VENCRYPT_X509VNC: 1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "vencrypt+x509+vnc"; 1335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_VENCRYPT_X509PLAIN: 1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "vencrypt+x509+plain"; 1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_VENCRYPT_TLSSASL: 1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "vencrypt+tls+sasl"; 1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_VENCRYPT_X509SASL: 1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "vencrypt+x509+sasl"; 1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "vencrypt"; 1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "vencrypt"; 1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_SASL: 1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "sasl"; 1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return "unknown"; 1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void do_info_vnc_client(Monitor *mon, VncState *client) 1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *clientAddr = 1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_socket_remote_addr(" address: %s:%s\n", 1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner client->csock); 1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!clientAddr) 1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "Client:\n"); 1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "%s", clientAddr); 1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(clientAddr); 1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_VNC_TLS 1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (client->tls.session && 1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner client->tls.dname) 1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, " x509 dname: %s\n", client->tls.dname); 1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, " x509 dname: none\n"); 1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VNC_SASL 1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (client->sasl.conn && 1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner client->sasl.username) 1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, " username: %s\n", client->sasl.username); 1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, " username: none\n"); 1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid do_info_vnc(Monitor *mon) 1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vnc_display == NULL || vnc_display->display == NULL) { 1825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "Server: disabled\n"); 1835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 1845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *serverAddr = vnc_socket_local_addr(" address: %s:%s\n", 1855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_display->lsock); 1865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!serverAddr) 1885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 1895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "Server:\n"); 1915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "%s", serverAddr); 1925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(serverAddr); 1935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, " auth: %s\n", vnc_auth_name(vnc_display)); 1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vnc_display->clients) { 1965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncState *client = vnc_display->clients; 1975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (client) { 1985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner do_info_vnc_client(mon, client); 1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner client = client->next; 2005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "Client: none\n"); 2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline uint32_t vnc_has_feature(VncState *vs, int feature) { 2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return (vs->features & (1 << feature)); 2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* TODO 2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1) Get the queue working for IO. 2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2) there is some weirdness when using the -S option (the screen is grey 2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project and not totally invalidated 2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3) resolutions > 1024 2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/ 2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void vnc_update_client(void *opaque); 2195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vnc_disconnect_start(VncState *vs); 2205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vnc_disconnect_finish(VncState *vs); 2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vnc_colordepth(VncState *vs); 2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void vnc_set_bit(uint32_t *d, int k) 2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project d[k >> 5] |= 1 << (k & 0x1f); 2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void vnc_clear_bit(uint32_t *d, int k) 2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project d[k >> 5] &= ~(1 << (k & 0x1f)); 2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void vnc_set_bits(uint32_t *d, int n, int nb_words) 2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int j; 2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project j = 0; 2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while (n >= 32) { 2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project d[j++] = -1; 2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n -= 32; 2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n > 0) 2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project d[j++] = (1 << n) - 1; 2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while (j < nb_words) 2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project d[j++] = 0; 2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline int vnc_get_bit(const uint32_t *d, int k) 2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (d[k >> 5] >> (k & 0x1f)) & 1; 2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2, 2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int nb_words) 2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i; 2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for(i = 0; i < nb_words; i++) { 2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((d1[i] & d2[i]) != 0) 2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vnc_update(VncState *vs, int x, int y, int w, int h) 2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct VncSurface *s = &vs->guest; 2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i; 2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project h += y; 2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* round x down to ensure the loop only spans one 16-pixel block per, 2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iteration. otherwise, if (x % 16) != 0, the last iteration may span 2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project two 16-pixel blocks but we only mark the first as dirty 2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project w += (x % 16); 2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project x -= (x % 16); 2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner x = MIN(x, s->ds->width); 2805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner y = MIN(y, s->ds->height); 2815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner w = MIN(x + w, s->ds->width) - x; 2825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner h = MIN(h, s->ds->height); 2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (; y < h; y++) 2855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = 0; i < w; i += 16) 2865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_set_bit(s->dirty[y], (x + i) / 16); 2875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h) 2905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncDisplay *vd = ds->opaque; 2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncState *vs = vd->clients; 2935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (vs != NULL) { 2945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_update(vs, x, y, w, h); 2955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs = vs->next; 2965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h, 3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int32_t encoding) 3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u16(vs, x); 3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u16(vs, y); 3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u16(vs, w); 3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u16(vs, h); 3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_s32(vs, encoding); 3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid buffer_reserve(Buffer *buffer, size_t len) 3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((buffer->capacity - buffer->offset) < len) { 3135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buffer->capacity += (len + 1024); 3145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buffer->buffer = qemu_realloc(buffer->buffer, buffer->capacity); 3155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (buffer->buffer == NULL) { 3165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "vnc: out of memory\n"); 3175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner exit(1); 3185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint buffer_empty(Buffer *buffer) 3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return buffer->offset == 0; 3255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneruint8_t *buffer_end(Buffer *buffer) 3285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return buffer->buffer + buffer->offset; 3305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid buffer_reset(Buffer *buffer) 3335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buffer->offset = 0; 3355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid buffer_append(Buffer *buffer, const void *data, size_t len) 3385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(buffer->buffer + buffer->offset, data, len); 3405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buffer->offset += len; 3415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vnc_resize(VncState *vs) 3445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DisplayState *ds = vs->ds; 3465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int size_changed; 3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* guest surface */ 3495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!vs->guest.ds) 3505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->guest.ds = qemu_mallocz(sizeof(*vs->guest.ds)); 3515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ds_get_bytes_per_pixel(ds) != vs->guest.ds->pf.bytes_per_pixel) 3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project console_color_init(ds); 3535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_colordepth(vs); 3545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size_changed = ds_get_width(ds) != vs->guest.ds->width || 3555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ds_get_height(ds) != vs->guest.ds->height; 3565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *(vs->guest.ds) = *(ds->surface); 3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size_changed) { 3585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->csock != -1 && vnc_has_feature(vs, VNC_FEATURE_RESIZE)) { 3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u8(vs, 0); /* msg id */ 3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u8(vs, 0); 3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u16(vs, 1); /* number of rects */ 3625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds), 3635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_ENCODING_DESKTOPRESIZE); 3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_flush(vs); 3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memset(vs->guest.dirty, 0xFF, sizeof(vs->guest.dirty)); 3685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* server surface */ 3705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!vs->server.ds) 3715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->server.ds = qemu_mallocz(sizeof(*vs->server.ds)); 3725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->server.ds->data) 3735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(vs->server.ds->data); 3745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *(vs->server.ds) = *(ds->surface); 3755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->server.ds->data = qemu_mallocz(vs->server.ds->linesize * 3765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->server.ds->height); 3775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memset(vs->server.dirty, 0xFF, sizeof(vs->guest.dirty)); 3785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vnc_dpy_resize(DisplayState *ds) 3815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncDisplay *vd = ds->opaque; 3835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncState *vs = vd->clients; 3845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (vs != NULL) { 3855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_resize(vs); 3865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs = vs->next; 3875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* fastest code */ 3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void vnc_write_pixels_copy(VncState *vs, void *pixels, int size) 3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write(vs, pixels, size); 3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* slowest but generic code. */ 3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v) 3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint8_t r, g, b; 4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner r = ((((v & vs->server.ds->pf.rmask) >> vs->server.ds->pf.rshift) << vs->clientds.pf.rbits) >> 4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->server.ds->pf.rbits); 4035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner g = ((((v & vs->server.ds->pf.gmask) >> vs->server.ds->pf.gshift) << vs->clientds.pf.gbits) >> 4045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->server.ds->pf.gbits); 4055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner b = ((((v & vs->server.ds->pf.bmask) >> vs->server.ds->pf.bshift) << vs->clientds.pf.bbits) >> 4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->server.ds->pf.bbits); 4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner v = (r << vs->clientds.pf.rshift) | 4085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (g << vs->clientds.pf.gshift) | 4095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (b << vs->clientds.pf.bshift); 4105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch(vs->clientds.pf.bytes_per_pixel) { 4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[0] = v; 4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 4155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) { 4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[0] = v >> 8; 4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[1] = v; 4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[1] = v >> 8; 4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[0] = v; 4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: 4255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) { 4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[0] = v >> 24; 4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[1] = v >> 16; 4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[2] = v >> 8; 4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[3] = v; 4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[3] = v >> 24; 4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[2] = v >> 16; 4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[1] = v >> 8; 4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[0] = v; 4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size) 4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint8_t buf[4]; 4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->server.ds->pf.bytes_per_pixel == 4) { 4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t *pixels = pixels1; 4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int n, i; 4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = size >> 2; 4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for(i = 0; i < n; i++) { 4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_convert_pixel(vs, buf, pixels[i]); 4505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel); 4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (vs->server.ds->pf.bytes_per_pixel == 2) { 4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint16_t *pixels = pixels1; 4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int n, i; 4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = size >> 1; 4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for(i = 0; i < n; i++) { 4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_convert_pixel(vs, buf, pixels[i]); 4585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel); 4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (vs->server.ds->pf.bytes_per_pixel == 1) { 4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint8_t *pixels = pixels1; 4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int n, i; 4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = size; 4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for(i = 0; i < n; i++) { 4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_convert_pixel(vs, buf, pixels[i]); 4665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel); 4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n"); 4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h) 4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i; 4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint8_t *row; 4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner row = vs->server.ds->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds); 4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < h; i++) { 4805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->write_pixels(vs, row, w * ds_get_bytes_per_pixel(vs->ds)); 4815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner row += ds_get_linesize(vs->ds); 4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h) 4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ptr[0] = ((x & 0x0F) << 4) | (y & 0x0F); 4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F); 4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define BPP 8 4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "vnchextile.h" 4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef BPP 4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define BPP 16 4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "vnchextile.h" 4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef BPP 4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define BPP 32 5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "vnchextile.h" 5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef BPP 5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GENERIC 5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define BPP 8 5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "vnchextile.h" 5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef BPP 5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef GENERIC 5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GENERIC 5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define BPP 16 5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "vnchextile.h" 5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef BPP 5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef GENERIC 5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GENERIC 5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define BPP 32 5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "vnchextile.h" 5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef BPP 5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef GENERIC 5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, int h) 5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i, j; 5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int has_fg, has_bg; 5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint8_t *last_fg, *last_bg; 5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner last_fg = (uint8_t *) qemu_malloc(vs->server.ds->pf.bytes_per_pixel); 5285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner last_bg = (uint8_t *) qemu_malloc(vs->server.ds->pf.bytes_per_pixel); 5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project has_fg = has_bg = 0; 5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (j = y; j < (y + h); j += 16) { 5315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = x; i < (x + w); i += 16) { 5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->send_hextile_tile(vs, i, j, 5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project MIN(16, x + w - i), MIN(16, y + h - j), 5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project last_bg, last_fg, &has_bg, &has_fg); 5355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project free(last_fg); 5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project free(last_bg); 5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vnc_zlib_init(VncState *vs) 5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 5445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int i; 5455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i=0; i<(sizeof(vs->zlib_stream) / sizeof(z_stream)); i++) 5465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->zlib_stream[i].opaque = NULL; 5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vnc_zlib_start(VncState *vs) 5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 5515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buffer_reset(&vs->zlib); 5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // make the output buffer be the zlib buffer, so we can compress it later 5545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->zlib_tmp = vs->output; 5555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->output = vs->zlib; 5565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int vnc_zlib_stop(VncState *vs, int stream_id) 5595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 5605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner z_streamp zstream = &vs->zlib_stream[stream_id]; 5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int previous_out; 5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // switch back to normal output/zlib buffers 5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->zlib = vs->output; 5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->output = vs->zlib_tmp; 5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // compress the zlib buffer 5685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // initialize the stream 5705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // XXX need one stream per session 5715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (zstream->opaque != vs) { 5725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int err; 5735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("VNC: initializing zlib stream %d\n", stream_id); 5755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("VNC: opaque = %p | vs = %p\n", zstream->opaque, vs); 5765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner zstream->zalloc = Z_NULL; 5775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner zstream->zfree = Z_NULL; 5785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner err = deflateInit2(zstream, vs->tight_compression, Z_DEFLATED, MAX_WBITS, 5805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); 5815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (err != Z_OK) { 5835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "VNC: error initializing zlib\n"); 5845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 5855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner zstream->opaque = vs; 5885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // XXX what to do if tight_compression changed in between? 5915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // reserve memory in output buffer 5935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buffer_reserve(&vs->output, vs->zlib.offset + 64); 5945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // set pointers 5965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner zstream->next_in = vs->zlib.buffer; 5975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner zstream->avail_in = vs->zlib.offset; 5985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner zstream->next_out = vs->output.buffer + vs->output.offset; 5995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner zstream->avail_out = vs->output.capacity - vs->output.offset; 6005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner zstream->data_type = Z_BINARY; 6015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner previous_out = zstream->total_out; 6025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // start encoding 6045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) { 6055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "VNC: error during zlib compression\n"); 6065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->output.offset = vs->output.capacity - zstream->avail_out; 6105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return zstream->total_out - previous_out; 6115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void send_framebuffer_update_zlib(VncState *vs, int x, int y, int w, int h) 6145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int old_offset, new_offset, bytes_written; 6165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_ZLIB); 6185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // remember where we put in the follow-up size 6205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner old_offset = vs->output.offset; 6215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_s32(vs, 0); 6225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // compress the stream 6245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_zlib_start(vs); 6255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner send_framebuffer_update_raw(vs, x, y, w, h); 6265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bytes_written = vnc_zlib_stop(vs, 0); 6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (bytes_written == -1) 6295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 6305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // hack in the size 6325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner new_offset = vs->output.offset; 6335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->output.offset = old_offset; 6345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u32(vs, bytes_written); 6355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->output.offset = new_offset; 6365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void send_framebuffer_update(VncState *vs, int x, int y, int w, int h) 6395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch(vs->vnc_encoding) { 6415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_ENCODING_ZLIB: 6425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner send_framebuffer_update_zlib(vs, x, y, w, h); 6435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 6445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_ENCODING_HEXTILE: 6455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE); 6465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner send_framebuffer_update_hextile(vs, x, y, w, h); 6475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 6485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 6495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW); 6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner send_framebuffer_update_raw(vs, x, y, w, h); 6515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h) 6565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u8(vs, 0); /* msg id */ 6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u8(vs, 0); 6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u16(vs, 1); /* number of rects */ 6605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT); 6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u16(vs, src_x); 6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u16(vs, src_y); 6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_flush(vs); 6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h) 6675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncDisplay *vd = ds->opaque; 6695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncState *vs, *vn; 6705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (vs = vd->clients; vs != NULL; vs = vn) { 6725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vn = vs->next; 6735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) { 6745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->force_update = 1; 6755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_update_client(vs); 6765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* vs might be free()ed here */ 6775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (vs = vd->clients; vs != NULL; vs = vs->next) { 6815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) 6825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h); 6835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else /* TODO */ 6845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_update(vs, dst_x, dst_y, w, h); 6855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int find_and_clear_dirty_height(struct VncSurface *s, 6895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int y, int last_x, int x) 6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int h; 6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (h = 1; h < (s->ds->height - y); h++) { 6945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int tmp_x; 6955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!vnc_get_bit(s->dirty[y + h], last_x)) 6965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 6975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (tmp_x = last_x; tmp_x < x; tmp_x++) 6985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_clear_bit(s->dirty[y + h], tmp_x); 6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return h; 7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void vnc_update_client(void *opaque) 7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VncState *vs = opaque; 7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (vs->need_update && vs->csock != -1) { 7085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int y; 7095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t *guest_row; 7105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t *server_row; 7115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int cmp_bytes; 7125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t width_mask[VNC_DIRTY_WORDS]; 7135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n_rectangles; 7145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int saved_offset; 7155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int has_dirty = 0; 7165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->output.offset && !vs->audio_cap && !vs->force_update) { 7185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* kernel send buffers are full -> drop frames to throttle */ 7195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL); 7205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 7215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vga_hw_update(); 7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 7265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Walk through the guest dirty map. 7275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Check and copy modified bits from guest to server surface. 7285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Update server dirty map. 7295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 7305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_set_bits(width_mask, (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS); 7315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cmp_bytes = 16 * ds_get_bytes_per_pixel(vs->ds); 7325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner guest_row = vs->guest.ds->data; 7335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner server_row = vs->server.ds->data; 7345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (y = 0; y < vs->guest.ds->height; y++) { 7355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vnc_and_bits(vs->guest.dirty[y], width_mask, VNC_DIRTY_WORDS)) { 7365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int x; 7375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t *guest_ptr; 7385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t *server_ptr; 7395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner guest_ptr = guest_row; 7415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner server_ptr = server_row; 7425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (x = 0; x < vs->guest.ds->width; 7445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) { 7455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!vnc_get_bit(vs->guest.dirty[y], (x / 16))) 7465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 7475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_clear_bit(vs->guest.dirty[y], (x / 16)); 7485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0) 7495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 7505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(server_ptr, guest_ptr, cmp_bytes); 7515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_set_bit(vs->server.dirty[y], (x / 16)); 7525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner has_dirty++; 7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner guest_row += ds_get_linesize(vs->ds); 7565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner server_row += ds_get_linesize(vs->ds); 7575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!has_dirty && !vs->audio_cap && !vs->force_update) { 7605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL); 7615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 7655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Send screen updates to the vnc client using the server 7665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * surface and server dirty map. guest surface updates 7675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * happening in parallel don't disturb us, the next pass will 7685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * send them to the client. 7695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 7705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner n_rectangles = 0; 7715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, 0); /* msg id */ 7725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, 0); 7735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner saved_offset = vs->output.offset; 7745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u16(vs, 0); 7755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (y = 0; y < vs->server.ds->height; y++) { 7775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int x; 7785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int last_x = -1; 7795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (x = 0; x < vs->server.ds->width / 16; x++) { 7805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vnc_get_bit(vs->server.dirty[y], x)) { 7815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (last_x == -1) { 7825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner last_x = x; 7835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_clear_bit(vs->server.dirty[y], x); 7855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 7865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (last_x != -1) { 7875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int h = find_and_clear_dirty_height(&vs->server, y, last_x, x); 7885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h); 7895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner n_rectangles++; 7905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner last_x = -1; 7925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (last_x != -1) { 7955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int h = find_and_clear_dirty_height(&vs->server, y, last_x, x); 7965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h); 7975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner n_rectangles++; 7985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF; 8015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF; 8025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_flush(vs); 8035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->force_update = 0; 8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (vs->csock != -1) { 8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL); 8095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 8105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_disconnect_finish(vs); 8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* audio */ 8165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void audio_capture_notify(void *opaque, audcnotification_e cmd) 8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VncState *vs = opaque; 8195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (cmd) { 8215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case AUD_CNOTIFY_DISABLE: 8225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, 255); 8235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, 1); 8245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u16(vs, 0); 8255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_flush(vs); 8265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 8275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case AUD_CNOTIFY_ENABLE: 8295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, 255); 8305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, 1); 8315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u16(vs, 1); 8325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_flush(vs); 8335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 8345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void audio_capture_destroy(void *opaque) 8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void audio_capture(void *opaque, void *buf, int size) 8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncState *vs = opaque; 8445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, 255); 8465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, 1); 8475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u16(vs, 2); 8485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u32(vs, size); 8495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write(vs, buf, size); 8505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_flush(vs); 8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void audio_add(VncState *vs) 8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner Monitor *mon = cur_mon; 8565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct audio_capture_ops ops; 8575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->audio_cap) { 8595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "audio already running\n"); 8605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 8615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ops.notify = audio_capture_notify; 8645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ops.destroy = audio_capture_destroy; 8655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ops.capture = audio_capture; 8665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->audio_cap = AUD_add_capture(&vs->as, &ops, vs); 8685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!vs->audio_cap) { 8695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "Failed to add audio capture\n"); 8705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void audio_del(VncState *vs) 8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->audio_cap) { 8765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner AUD_del_capture(vs->audio_cap, vs); 8775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->audio_cap = NULL; 8785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vnc_disconnect_start(VncState *vs) 8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->csock == -1) 8845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 8855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL); 8865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner closesocket(vs->csock); 8875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->csock = -1; 8885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 8895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vnc_disconnect_finish(VncState *vs) 8915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 8925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_del_timer(vs->timer); 8935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free_timer(vs->timer); 8945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->input.buffer) qemu_free(vs->input.buffer); 8955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->output.buffer) qemu_free(vs->output.buffer); 8965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VNC_TLS 8975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_tls_client_cleanup(vs); 8985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* CONFIG_VNC_TLS */ 8995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VNC_SASL 9005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_sasl_client_cleanup(vs); 9015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* CONFIG_VNC_SASL */ 9025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner audio_del(vs); 9035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncState *p, *parent = NULL; 9055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (p = vs->vd->clients; p != NULL; p = p->next) { 9065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (p == vs) { 9075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (parent) 9085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner parent->next = p->next; 9095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 9105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->vd->clients = p->next; 9115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 9125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 9135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner parent = p; 9145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 9155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!vs->vd->clients) 9165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dcl->idle = 1; 9175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(vs->server.ds->data); 9195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(vs->server.ds); 9205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(vs->guest.ds); 9215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(vs); 9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint vnc_client_io_error(VncState *vs, int ret, int last_errno) 9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ret == 0 || ret == -1) { 9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ret == -1) { 9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (last_errno) { 9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case EINTR: 9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case EAGAIN: 9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32 9325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case WSAEWOULDBLOCK: 9338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 9348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 9358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 9368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 9378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 9388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 9398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Closing down client sock: ret %d, errno %d\n", 9415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret, ret < 0 ? last_errno : 0); 9425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_disconnect_start(vs); 9435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ret; 9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid vnc_client_error(VncState *vs) 9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 9525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Closing down client sock: protocol error\n"); 9535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_disconnect_start(vs); 9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 9585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Called to write a chunk of data to the client socket. The data may 9595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * be the raw data, or may have already been encoded by SASL. 9605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * The data will be written either straight onto the socket, or 9615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * written via the GNUTLS wrappers, if TLS/SSL encryption is enabled 9625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 9635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * NB, it is theoretically possible to have 2 layers of encryption, 9645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * both SASL, and this TLS layer. It is highly unlikely in practice 9655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * though, since SASL encryption will typically be a no-op if TLS 9665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * is active 9675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 9685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Returns the number of bytes written, which may be less than 9695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * the requested 'datalen' if the socket would block. Returns 9705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * -1 on error, and disconnects the client socket. 9715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 9725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerlong vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen) 9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project long ret; 9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_VNC_TLS 9765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->tls.session) { 9775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = gnutls_write(vs->tls.session, data, datalen); 9785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 9795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret == GNUTLS_E_AGAIN) 9805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner errno = EAGAIN; 9815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 9825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner errno = EIO; 9835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 9845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* CONFIG_VNC_TLS */ 9875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = send(vs->csock, (const void *)data, datalen, 0); 9885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Wrote wire %p %zd -> %ld\n", data, datalen, ret); 9895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return vnc_client_io_error(vs, ret, socket_error()); 9905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 9915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 9945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Called to write buffered data to the client socket, when not 9955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * using any SASL SSF encryption layers. Will write as much data 9965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * as possible without blocking. If all buffered data is written, 9975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * will switch the FD poll() handler back to read monitoring. 9985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 9995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Returns the number of bytes written, which may be less than 10005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * the buffered output data if the socket would block. Returns 10015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * -1 on error, and disconnects the client socket. 10025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 10035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic long vnc_client_write_plain(VncState *vs) 10045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner long ret; 10065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VNC_SASL 10085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Write Plain: Pending output %p size %zd offset %zd. Wait SSF %d\n", 10095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->output.buffer, vs->output.capacity, vs->output.offset, 10105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->sasl.waitWriteSSF); 10115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->sasl.conn && 10135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->sasl.runSSF && 10145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->sasl.waitWriteSSF) { 10155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = vnc_client_write_buf(vs, vs->output.buffer, vs->sasl.waitWriteSSF); 10165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret) 10175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->sasl.waitWriteSSF -= ret; 10185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else 10195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* CONFIG_VNC_SASL */ 10205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = vnc_client_write_buf(vs, vs->output.buffer, vs->output.offset); 10218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!ret) 10225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 10238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memmove(vs->output.buffer, vs->output.buffer + ret, (vs->output.offset - ret)); 10258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->output.offset -= ret; 10268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (vs->output.offset == 0) { 10285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs); 10298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 10305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return ret; 10325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 10365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * First function called whenever there is data to be written to 10375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * the client socket. Will delegate actual work according to whether 10385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * SASL SSF layers are enabled (thus requiring encryption calls) 10395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 10405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid vnc_client_write(void *opaque) 10415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner long ret; 10435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncState *vs = opaque; 10445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VNC_SASL 10465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->sasl.conn && 10475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->sasl.runSSF && 10485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner !vs->sasl.waitWriteSSF) 10495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = vnc_client_write_sasl(vs); 10505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 10515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* CONFIG_VNC_SASL */ 10525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = vnc_client_write_plain(vs); 10538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 10548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting) 10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 10578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->read_handler = func; 10588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->read_handler_expect = expecting; 10598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 10635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Called to read a chunk of data from the client socket. The data may 10645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * be the raw data, or may need to be further decoded by SASL. 10655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * The data will be read either straight from to the socket, or 10665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * read via the GNUTLS wrappers, if TLS/SSL encryption is enabled 10675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 10685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * NB, it is theoretically possible to have 2 layers of encryption, 10695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * both SASL, and this TLS layer. It is highly unlikely in practice 10705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * though, since SASL encryption will typically be a no-op if TLS 10715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * is active 10725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 10735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Returns the number of bytes read, which may be less than 10745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * the requested 'datalen' if the socket would block. Returns 10755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * -1 on error, and disconnects the client socket. 10765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 10775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerlong vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen) 10788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project long ret; 10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_VNC_TLS 10815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->tls.session) { 10825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = gnutls_read(vs->tls.session, data, datalen); 10835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 10845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret == GNUTLS_E_AGAIN) 10855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner errno = EAGAIN; 10865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 10875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner errno = EIO; 10885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 10895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* CONFIG_VNC_TLS */ 10925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = recv(vs->csock, (void *)data, datalen, 0); 10935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Read wire %p %zd -> %ld\n", data, datalen, ret); 10945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return vnc_client_io_error(vs, ret, socket_error()); 10955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 10995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Called to read data from the client socket to the input buffer, 11005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * when not using any SASL SSF encryption layers. Will read as much 11015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * data as possible without blocking. 11025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 11035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Returns the number of bytes read. Returns -1 on error, and 11045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * disconnects the client socket. 11055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 11065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic long vnc_client_read_plain(VncState *vs) 11075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 11085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret; 11095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Read plain %p size %zd offset %zd\n", 11105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->input.buffer, vs->input.capacity, vs->input.offset); 11115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buffer_reserve(&vs->input, 4096); 11125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = vnc_client_read_buf(vs, buffer_end(&vs->input), 4096); 11135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!ret) 11145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->input.offset += ret; 11165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return ret; 11175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 11185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 11215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * First function called whenever there is more data to be read from 11225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * the client socket. Will delegate actual work according to whether 11235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * SASL SSF layers are enabled (thus requiring decryption calls) 11245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 11255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid vnc_client_read(void *opaque) 11265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 11275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncState *vs = opaque; 11285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner long ret; 11295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VNC_SASL 11315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->sasl.conn && vs->sasl.runSSF) 11325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = vnc_client_read_sasl(vs); 11335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 11345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* CONFIG_VNC_SASL */ 11355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = vnc_client_read_plain(vs); 11365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!ret) { 11375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->csock == -1) 11385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_disconnect_finish(vs); 11395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 11405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) { 11435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size_t len = vs->read_handler_expect; 11445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret; 11455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = vs->read_handler(vs, vs->input.buffer, len); 11475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->csock == -1) { 11485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_disconnect_finish(vs); 11495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 11505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 11515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!ret) { 11535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memmove(vs->input.buffer, vs->input.buffer + len, (vs->input.offset - len)); 11545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->input.offset -= len; 11555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 11565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->read_handler_expect = ret; 11575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid vnc_write(VncState *vs, const void *data, size_t len) 11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buffer_reserve(&vs->output, len); 11648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->csock != -1 && buffer_empty(&vs->output)) { 11665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs); 11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 11688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buffer_append(&vs->output, data, len); 11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid vnc_write_s32(VncState *vs, int32_t value) 11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u32(vs, *(uint32_t *)&value); 11758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid vnc_write_u32(VncState *vs, uint32_t value) 11788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint8_t buf[4]; 11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[0] = (value >> 24) & 0xFF; 11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[1] = (value >> 16) & 0xFF; 11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[2] = (value >> 8) & 0xFF; 11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[3] = value & 0xFF; 11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write(vs, buf, 4); 11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid vnc_write_u16(VncState *vs, uint16_t value) 11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint8_t buf[2]; 11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[0] = (value >> 8) & 0xFF; 11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project buf[1] = value & 0xFF; 11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write(vs, buf, 2); 11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid vnc_write_u8(VncState *vs, uint8_t value) 12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write(vs, (char *)&value, 1); 12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid vnc_flush(VncState *vs) 12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 12065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->csock != -1 && vs->output.offset) 12075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_client_write(vs); 12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneruint8_t read_u8(uint8_t *data, size_t offset) 12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return data[offset]; 12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneruint16_t read_u16(uint8_t *data, size_t offset) 12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 12178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF); 12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint32_t read_s32(uint8_t *data, size_t offset) 12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 12228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) | 12235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (data[offset + 2] << 8) | data[offset + 3]); 12248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneruint32_t read_u32(uint8_t *data, size_t offset) 12278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 12288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ((data[offset] << 24) | (data[offset + 1] << 16) | 12295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (data[offset + 2] << 8) | data[offset + 3]); 12308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void client_cut_text(VncState *vs, size_t len, uint8_t *text) 12335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 12348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void check_pointer_type_change(VncState *vs, int absolute) 12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 12385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE) && vs->absolute != absolute) { 12395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, 0); 12405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, 0); 12415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u16(vs, 1); 12425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_framebuffer_update(vs, absolute, 0, 12435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ds_get_width(vs->ds), ds_get_height(vs->ds), 12445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_ENCODING_POINTER_TYPE_CHANGE); 12455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_flush(vs); 12468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 12478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->absolute = absolute; 12488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void pointer_event(VncState *vs, int button_mask, int x, int y) 12518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 12528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int buttons = 0; 12538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int dz = 0; 12548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (button_mask & 0x01) 12565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buttons |= MOUSE_EVENT_LBUTTON; 12578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (button_mask & 0x02) 12585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buttons |= MOUSE_EVENT_MBUTTON; 12598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (button_mask & 0x04) 12605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buttons |= MOUSE_EVENT_RBUTTON; 12618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (button_mask & 0x08) 12625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dz = -1; 12638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (button_mask & 0x10) 12645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dz = 1; 12658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (vs->absolute) { 12675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_mouse_event(x * 0x7FFF / (ds_get_width(vs->ds) - 1), 12685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner y * 0x7FFF / (ds_get_height(vs->ds) - 1), 12695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dz, buttons); 12705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) { 12715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner x -= 0x7FFF; 12725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner y -= 0x7FFF; 12735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_mouse_event(x, y, dz, buttons); 12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 12765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->last_x != -1) 12775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_mouse_event(x - vs->last_x, 12785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner y - vs->last_y, 12795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dz, buttons); 12805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->last_x = x; 12815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->last_y = y; 12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project check_pointer_type_change(vs, kbd_mouse_is_absolute()); 12858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void reset_keys(VncState *vs) 12888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i; 12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for(i = 0; i < 256; i++) { 12918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (vs->modifiers_state[i]) { 12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i & 0x80) 12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_put_keycode(0xe0); 12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_put_keycode(i | 0x80); 12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->modifiers_state[i] = 0; 12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void press_key(VncState *vs, int keysym) 13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 13025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keycode(keysym2scancode(vs->vd->kbd_layout, keysym) & 0x7f); 13035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keycode(keysym2scancode(vs->vd->kbd_layout, keysym) | 0x80); 13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 13058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void do_key_event(VncState *vs, int down, int keycode, int sym) 13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 13088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* QEMU console switch */ 13098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(keycode) { 13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x2a: /* Left Shift */ 13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x36: /* Right Shift */ 13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x1d: /* Left CTRL */ 13138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x9d: /* Right CTRL */ 13148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x38: /* Left ALT */ 13158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xb8: /* Right ALT */ 13168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (down) 13178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->modifiers_state[keycode] = 1; 13188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 13198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->modifiers_state[keycode] = 0; 13208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x02 ... 0x0a: /* '1' to '9' keys */ 13228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) { 13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Reset the modifiers sent to the current console */ 13248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project reset_keys(vs); 13258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project console_select(keycode - 0x02); 13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 13278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 13295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x3a: /* CapsLock */ 13305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x45: /* NumLock */ 13318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!down) 13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->modifiers_state[keycode] ^= 1; 13338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 13358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (keycode_is_keypad(vs->vd->kbd_layout, keycode)) { 13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* If the numlock state needs to change then simulate an additional 13388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project keypress before sending this one. This will happen if the user 13398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project toggles numlock away from the VNC window. 13408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 13415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) { 13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!vs->modifiers_state[0x45]) { 13438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->modifiers_state[0x45] = 1; 13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project press_key(vs, 0xff7f); 13458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 13468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 13478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (vs->modifiers_state[0x45]) { 13488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->modifiers_state[0x45] = 0; 13498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project press_key(vs, 0xff7f); 13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (is_graphic_console()) { 13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (keycode & 0x80) 13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_put_keycode(0xe0); 13578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (down) 13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_put_keycode(keycode & 0x7f); 13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 13608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_put_keycode(keycode | 0x80); 13618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 13628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* QEMU console emulation */ 13638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (down) { 13645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int numlock = vs->modifiers_state[0x45]; 13658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (keycode) { 13668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x2a: /* Left Shift */ 13678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x36: /* Right Shift */ 13688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x1d: /* Left CTRL */ 13698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x9d: /* Right CTRL */ 13708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x38: /* Left ALT */ 13718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xb8: /* Right ALT */ 13728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 13738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc8: 13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_put_keysym(QEMU_KEY_UP); 13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 13768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xd0: 13778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_put_keysym(QEMU_KEY_DOWN); 13788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xcb: 13808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_put_keysym(QEMU_KEY_LEFT); 13818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 13828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xcd: 13838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_put_keysym(QEMU_KEY_RIGHT); 13848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xd3: 13868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_put_keysym(QEMU_KEY_DELETE); 13878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 13888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc7: 13898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_put_keysym(QEMU_KEY_HOME); 13908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 13918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xcf: 13928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_put_keysym(QEMU_KEY_END); 13938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 13948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc9: 13958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_put_keysym(QEMU_KEY_PAGEUP); 13968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 13978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xd1: 13988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_put_keysym(QEMU_KEY_PAGEDOWN); 13998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 14005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x47: 14025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keysym(numlock ? '7' : QEMU_KEY_HOME); 14035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x48: 14055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keysym(numlock ? '8' : QEMU_KEY_UP); 14065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x49: 14085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keysym(numlock ? '9' : QEMU_KEY_PAGEUP); 14095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x4b: 14115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keysym(numlock ? '4' : QEMU_KEY_LEFT); 14125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x4c: 14145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keysym('5'); 14155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x4d: 14175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keysym(numlock ? '6' : QEMU_KEY_RIGHT); 14185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x4f: 14205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keysym(numlock ? '1' : QEMU_KEY_END); 14215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x50: 14235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keysym(numlock ? '2' : QEMU_KEY_DOWN); 14245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x51: 14265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keysym(numlock ? '3' : QEMU_KEY_PAGEDOWN); 14275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x52: 14295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keysym('0'); 14305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x53: 14325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keysym(numlock ? '.' : QEMU_KEY_DELETE); 14335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0xb5: 14365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keysym('/'); 14375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x37: 14395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keysym('*'); 14405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x4a: 14425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keysym('-'); 14435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x4e: 14455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keysym('+'); 14465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0x9c: 14485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kbd_put_keysym('\n'); 14495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 14528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_put_keysym(sym); 14538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 14548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 14588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void key_event(VncState *vs, int down, uint32_t sym) 14608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 14618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int keycode; 14628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sym >= 'A' && sym <= 'Z' && is_graphic_console()) 14645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sym = sym - 'A' + 'a'; 14658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner keycode = keysym2scancode(vs->vd->kbd_layout, sym & 0xFFFF); 14678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project do_key_event(vs, down, keycode, sym); 14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 14698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void ext_key_event(VncState *vs, int down, 14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t sym, uint16_t keycode) 14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 14738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* if the user specifies a keyboard layout, always use it */ 14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (keyboard_layout) 14758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project key_event(vs, down, sym); 14768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project do_key_event(vs, down, keycode, sym); 14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void framebuffer_update_request(VncState *vs, int incremental, 14815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int x_position, int y_position, 14825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int w, int h) 14835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 14845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (x_position > ds_get_width(vs->ds)) 14855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner x_position = ds_get_width(vs->ds); 14865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (y_position > ds_get_height(vs->ds)) 14875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner y_position = ds_get_height(vs->ds); 14885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (x_position + w >= ds_get_width(vs->ds)) 14895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner w = ds_get_width(vs->ds) - x_position; 14905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (y_position + h >= ds_get_height(vs->ds)) 14915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner h = ds_get_height(vs->ds) - y_position; 14928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i; 14948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->need_update = 1; 14958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!incremental) { 14965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->force_update = 1; 14975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = 0; i < h; i++) { 14985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_set_bits(vs->guest.dirty[y_position + i], 14995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS); 15005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_set_bits(vs->server.dirty[y_position + i], 15015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS); 15025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 15048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void send_ext_key_event_ack(VncState *vs) 15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u8(vs, 0); 15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u8(vs, 0); 15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u16(vs, 1); 15115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds), 15125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_ENCODING_EXT_KEY_EVENT); 15135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_flush(vs); 15145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 15155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void send_ext_audio_ack(VncState *vs) 15175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 15185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, 0); 15195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, 0); 15205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u16(vs, 1); 15215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds), 15225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_ENCODING_AUDIO); 15238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_flush(vs); 15248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) 15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 15288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i; 15295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned int enc = 0; 15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_zlib_init(vs); 15325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->features = 0; 15335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->vnc_encoding = 0; 15345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->tight_compression = 9; 15355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->tight_quality = 9; 15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->absolute = -1; 15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = n_encodings - 1; i >= 0; i--) { 15395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner enc = encodings[i]; 15405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (enc) { 15415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_ENCODING_RAW: 15425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->vnc_encoding = enc; 15435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 15445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_ENCODING_COPYRECT: 15455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->features |= VNC_FEATURE_COPYRECT_MASK; 15465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 15475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_ENCODING_HEXTILE: 15485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->features |= VNC_FEATURE_HEXTILE_MASK; 15495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->vnc_encoding = enc; 15505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 15515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_ENCODING_ZLIB: 15525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->features |= VNC_FEATURE_ZLIB_MASK; 15535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->vnc_encoding = enc; 15545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 15555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_ENCODING_DESKTOPRESIZE: 15565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->features |= VNC_FEATURE_RESIZE_MASK; 15575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 15585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_ENCODING_POINTER_TYPE_CHANGE: 15595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->features |= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK; 15605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 15615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_ENCODING_EXT_KEY_EVENT: 15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project send_ext_key_event_ack(vs); 15638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_ENCODING_AUDIO: 15655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner send_ext_audio_ack(vs); 15665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 15675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_ENCODING_WMVi: 15685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->features |= VNC_FEATURE_WMVI_MASK; 15695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 15705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9: 15715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->tight_compression = (enc & 0x0F); 15725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 15735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_ENCODING_QUALITYLEVEL0 ... VNC_ENCODING_QUALITYLEVEL0 + 9: 15745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->tight_quality = (enc & 0x0F); 15755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 15765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 15775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Unknown encoding: %d (0x%.8x): %d\n", i, enc, enc); 15788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 15818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project check_pointer_type_change(vs, kbd_mouse_is_absolute()); 15838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 15848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void set_pixel_conversion(VncState *vs) 15868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 15875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) == 15885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) && 15895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner !memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) { 15908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->write_pixels = vnc_write_pixels_copy; 15915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (vs->ds->surface->pf.bits_per_pixel) { 15925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 8: 15935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->send_hextile_tile = send_hextile_tile_8; 15945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 15955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 16: 15965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->send_hextile_tile = send_hextile_tile_16; 15975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 15985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 32: 15995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->send_hextile_tile = send_hextile_tile_32; 16005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 16018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 16025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 16038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->write_pixels = vnc_write_pixels_generic; 16045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (vs->ds->surface->pf.bits_per_pixel) { 16055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 8: 16065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->send_hextile_tile = send_hextile_tile_generic_8; 16075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 16085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 16: 16095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->send_hextile_tile = send_hextile_tile_generic_16; 16105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 16115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 32: 16125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->send_hextile_tile = send_hextile_tile_generic_32; 16135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 16145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 16175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void set_pixel_format(VncState *vs, 16195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int bits_per_pixel, int depth, 16205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int big_endian_flag, int true_color_flag, 16215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int red_max, int green_max, int blue_max, 16225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int red_shift, int green_shift, int blue_shift) 16235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 16245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!true_color_flag) { 16255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_client_error(vs); 16265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 16278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 16288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->clientds = *(vs->guest.ds); 16305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->clientds.pf.rmax = red_max; 16315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner count_bits(vs->clientds.pf.rbits, red_max); 16325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->clientds.pf.rshift = red_shift; 16335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->clientds.pf.rmask = red_max << red_shift; 16345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->clientds.pf.gmax = green_max; 16355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner count_bits(vs->clientds.pf.gbits, green_max); 16365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->clientds.pf.gshift = green_shift; 16375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->clientds.pf.gmask = green_max << green_shift; 16385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->clientds.pf.bmax = blue_max; 16395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner count_bits(vs->clientds.pf.bbits, blue_max); 16405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->clientds.pf.bshift = blue_shift; 16415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->clientds.pf.bmask = blue_max << blue_shift; 16425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->clientds.pf.bits_per_pixel = bits_per_pixel; 16435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->clientds.pf.bytes_per_pixel = bits_per_pixel / 8; 16445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->clientds.pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel; 16455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->clientds.flags = big_endian_flag ? QEMU_BIG_ENDIAN_FLAG : 0x00; 16465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner set_pixel_conversion(vs); 16488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vga_hw_invalidate(); 16508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vga_hw_update(); 16518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 16528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void pixel_format_message (VncState *vs) { 16548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char pad[3] = { 0, 0, 0 }; 16558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, vs->ds->surface->pf.bits_per_pixel); /* bits-per-pixel */ 16575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, vs->ds->surface->pf.depth); /* depth */ 16588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 165920894ae3fa98f82da925fbeb72e616eef509758aDavid 'Digit' Turner#ifdef HOST_WORDS_BIGENDIAN 16608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u8(vs, 1); /* big-endian-flag */ 16618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 16628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u8(vs, 0); /* big-endian-flag */ 16638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 16648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u8(vs, 1); /* true-color-flag */ 16655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u16(vs, vs->ds->surface->pf.rmax); /* red-max */ 16665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u16(vs, vs->ds->surface->pf.gmax); /* green-max */ 16675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u16(vs, vs->ds->surface->pf.bmax); /* blue-max */ 16685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, vs->ds->surface->pf.rshift); /* red-shift */ 16695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, vs->ds->surface->pf.gshift); /* green-shift */ 16705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, vs->ds->surface->pf.bshift); /* blue-shift */ 16715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->ds->surface->pf.bits_per_pixel == 32) 16728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->send_hextile_tile = send_hextile_tile_32; 16735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (vs->ds->surface->pf.bits_per_pixel == 16) 16748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->send_hextile_tile = send_hextile_tile_16; 16755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (vs->ds->surface->pf.bits_per_pixel == 8) 16768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->send_hextile_tile = send_hextile_tile_8; 16775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->clientds = *(vs->ds->surface); 16785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->clientds.flags &= ~QEMU_ALLOCATED_FLAG; 16798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->write_pixels = vnc_write_pixels_copy; 16808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write(vs, pad, 3); /* padding */ 16828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 16838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vnc_dpy_setdata(DisplayState *ds) 16858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 16865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* We don't have to do anything */ 16875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 16888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vnc_colordepth(VncState *vs) 16905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 16915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vnc_has_feature(vs, VNC_FEATURE_WMVI)) { 16928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Sending a WMVi message to notify the client*/ 16938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u8(vs, 0); /* msg id */ 16948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u8(vs, 0); 16958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u16(vs, 1); /* number of rects */ 16965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), 16975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ds_get_height(vs->ds), VNC_ENCODING_WMVi); 16988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pixel_format_message(vs); 16998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_flush(vs); 17008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 17015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner set_pixel_conversion(vs); 17028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 17038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 17048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int protocol_client_msg(VncState *vs, uint8_t *data, size_t len) 17068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 17078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i; 17088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint16_t limit; 17098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (data[0]) { 17118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 17125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len == 1) 17135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 20; 17148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5), 17165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner read_u8(data, 6), read_u8(data, 7), 17175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner read_u16(data, 8), read_u16(data, 10), 17185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner read_u16(data, 12), read_u8(data, 14), 17195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner read_u8(data, 15), read_u8(data, 16)); 17205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 17215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 2: 17225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len == 1) 17235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 4; 17245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len == 4) { 17265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner limit = read_u16(data, 2); 17275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (limit > 0) 17285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 4 + (limit * 4); 17295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else 17305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner limit = read_u16(data, 2); 17315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = 0; i < limit; i++) { 17335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int32_t val = read_s32(data, 4 + (i * 4)); 17345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(data + 4 + (i * 4), &val, sizeof(val)); 17355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner set_encodings(vs, (int32_t *)(data + 4), limit); 17385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 17398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 17405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len == 1) 17415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 10; 17428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner framebuffer_update_request(vs, 17445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner read_u8(data, 1), read_u16(data, 2), read_u16(data, 4), 17455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner read_u16(data, 6), read_u16(data, 8)); 17465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 17478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: 17485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len == 1) 17495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 8; 17508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner key_event(vs, read_u8(data, 1), read_u32(data, 4)); 17525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 17538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: 17545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len == 1) 17555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 6; 17568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4)); 17585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 17598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: 17605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len == 1) 17615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 8; 17628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len == 8) { 17648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t dlen = read_u32(data, 4); 17658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dlen > 0) 17668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 8 + dlen; 17678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 17688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner client_cut_text(vs, read_u32(data, 4), data + 8); 17705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 17718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 255: 17728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len == 1) 17738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 2; 17748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (read_u8(data, 1)) { 17768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 17778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len == 2) 17788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 12; 17798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ext_key_event(vs, read_u16(data, 2), 17818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project read_u32(data, 4), read_u32(data, 8)); 17828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 1: 17845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len == 2) 17855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 4; 17865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (read_u16 (data, 2)) { 17885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0: 17895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner audio_add(vs); 17905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 17915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 1: 17925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner audio_del(vs); 17935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 17945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 2: 17955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len == 4) 17965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 10; 17975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (read_u8(data, 4)) { 17985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0: vs->as.fmt = AUD_FMT_U8; break; 17995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 1: vs->as.fmt = AUD_FMT_S8; break; 18005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 2: vs->as.fmt = AUD_FMT_U16; break; 18015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 3: vs->as.fmt = AUD_FMT_S16; break; 18025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 4: vs->as.fmt = AUD_FMT_U32; break; 18035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 5: vs->as.fmt = AUD_FMT_S32; break; 18045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 18055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner printf("Invalid audio format %d\n", read_u8(data, 4)); 18065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_client_error(vs); 18075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 18085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 18095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->as.nchannels = read_u8(data, 5); 18105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->as.nchannels != 1 && vs->as.nchannels != 2) { 18115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner printf("Invalid audio channel coount %d\n", 18125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner read_u8(data, 5)); 18135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_client_error(vs); 18145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 18155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 18165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->as.freq = read_u32(data, 6); 18175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 18185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 18195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner printf ("Invalid audio message %d\n", read_u8(data, 4)); 18205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_client_error(vs); 18215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 18225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 18235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 18245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 18268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project printf("Msg: %d\n", read_u16(data, 0)); 18278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_client_error(vs); 18288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 18325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner printf("Msg: %d\n", data[0]); 18335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_client_error(vs); 18345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 18358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 18378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_read_when(vs, protocol_client_msg, 1); 18388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 18398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 18408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 18418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int protocol_client_init(VncState *vs, uint8_t *data, size_t len) 18428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 18438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char buf[1024]; 18448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int size; 18458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 18465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u16(vs, ds_get_width(vs->ds)); 18475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u16(vs, ds_get_height(vs->ds)); 18488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 18498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pixel_format_message(vs); 18508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 18518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (qemu_name) 18528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = snprintf(buf, sizeof(buf), "QEMU (%s)", qemu_name); 18538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 18548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = snprintf(buf, sizeof(buf), "QEMU"); 18558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 18568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u32(vs, size); 18578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write(vs, buf, size); 18588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_flush(vs); 18598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 18608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_read_when(vs, protocol_client_msg, 1); 18618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 18628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 18638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 18648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 18655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid start_client_init(VncState *vs) 18665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 18675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_read_when(vs, protocol_client_init, 1); 18685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 18695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void make_challenge(VncState *vs) 18718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 18728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i; 18738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 18748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project srand(time(NULL)+getpid()+getpid()*987654+rand()); 18758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 18768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0 ; i < sizeof(vs->challenge) ; i++) 18778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->challenge[i] = (int) (256.0*rand()/(RAND_MAX+1.0)); 18788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 18798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 18808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len) 18818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 18828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned char response[VNC_AUTH_CHALLENGE_SIZE]; 18838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i, j, pwlen; 18848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned char key[8]; 18858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 18865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!vs->vd->password || !vs->vd->password[0]) { 18875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("No password configured on server"); 18885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u32(vs, 1); /* Reject auth */ 18895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->minor >= 8) { 18905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static const char err[] = "Authentication failed"; 18915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u32(vs, sizeof(err)); 18925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write(vs, err, sizeof(err)); 18935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 18945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_flush(vs); 18955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_client_error(vs); 18965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 18978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 18998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE); 19008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 19018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Calculate the expected challenge response */ 19025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pwlen = strlen(vs->vd->password); 19038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i=0; i<sizeof(key); i++) 19045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner key[i] = i<pwlen ? vs->vd->password[i] : 0; 19058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project deskey(key, EN0); 19068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8) 19078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project des(response+j, response+j); 19088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 19098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Compare expected vs actual challenge response */ 19108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) { 19115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Client challenge reponse did not match\n"); 19125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u32(vs, 1); /* Reject auth */ 19135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->minor >= 8) { 19145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static const char err[] = "Authentication failed"; 19155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u32(vs, sizeof(err)); 19165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write(vs, err, sizeof(err)); 19175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 19185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_flush(vs); 19195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_client_error(vs); 19208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 19215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Accepting VNC challenge response\n"); 19225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u32(vs, 0); /* Accept auth */ 19235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_flush(vs); 19248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 19255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner start_client_init(vs); 19268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 19278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 19288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 19298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 19305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid start_auth_vnc(VncState *vs) 19318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 19328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project make_challenge(vs); 19338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Send client a 'random' challenge */ 19348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write(vs, vs->challenge, sizeof(vs->challenge)); 19358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_flush(vs); 19368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 19378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge)); 19388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 19398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 19408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 19418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int protocol_client_auth(VncState *vs, uint8_t *data, size_t len) 19428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 19438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* We only advertise 1 auth scheme at a time, so client 19448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * must pick the one we sent. Verify this */ 19455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (data[0] != vs->vd->auth) { /* Reject auth */ 19465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Reject auth %d because it didn't match advertized\n", (int)data[0]); 19478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u32(vs, 1); 19488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (vs->minor >= 8) { 19498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project static const char err[] = "Authentication failed"; 19508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u32(vs, sizeof(err)); 19518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write(vs, err, sizeof(err)); 19528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 19538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_client_error(vs); 19548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* Accept requested auth */ 19558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VNC_DEBUG("Client requested auth %d\n", (int)data[0]); 19565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (vs->vd->auth) { 19578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case VNC_AUTH_NONE: 19588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VNC_DEBUG("Accept auth none\n"); 19598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (vs->minor >= 8) { 19608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u32(vs, 0); /* Accept auth completion */ 19618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_flush(vs); 19628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 19635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner start_client_init(vs); 19648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 19668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case VNC_AUTH_VNC: 19678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VNC_DEBUG("Start VNC auth\n"); 19685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner start_auth_vnc(vs); 19695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 19708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 19718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_VNC_TLS 19728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case VNC_AUTH_VENCRYPT: 19738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VNC_DEBUG("Accept VeNCrypt auth\n");; 19745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner start_auth_vencrypt(vs); 19755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 19768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* CONFIG_VNC_TLS */ 19778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 19785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VNC_SASL 19795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case VNC_AUTH_SASL: 19805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Accept SASL auth\n"); 19815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner start_auth_sasl(vs); 19825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 19835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* CONFIG_VNC_SASL */ 19845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* Should not be possible, but just in case */ 19865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Reject auth %d server code bug\n", vs->vd->auth); 19878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u8(vs, 1); 19888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (vs->minor >= 8) { 19898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project static const char err[] = "Authentication failed"; 19908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u32(vs, sizeof(err)); 19918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write(vs, err, sizeof(err)); 19928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 19938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_client_error(vs); 19948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 19958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 19968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 19978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 19988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 19998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int protocol_version(VncState *vs, uint8_t *version, size_t len) 20008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 20018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char local[13]; 20028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 20038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(local, version, 12); 20048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project local[12] = 0; 20058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 20068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) { 20075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Malformed protocol version %s\n", local); 20085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_client_error(vs); 20095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 20108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 20118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor); 20128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (vs->major != 3 || 20135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (vs->minor != 3 && 20145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->minor != 4 && 20155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->minor != 5 && 20165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->minor != 7 && 20175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->minor != 8)) { 20185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Unsupported client version\n"); 20195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u32(vs, VNC_AUTH_INVALID); 20205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_flush(vs); 20215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_client_error(vs); 20225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 20238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 20248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Some broken clients report v3.4 or v3.5, which spec requires to be treated 20258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * as equivalent to v3.3 by servers 20268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 20278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (vs->minor == 4 || vs->minor == 5) 20285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->minor = 3; 20298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 20308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (vs->minor == 3) { 20315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vs->vd->auth == VNC_AUTH_NONE) { 20328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VNC_DEBUG("Tell client auth none\n"); 20335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u32(vs, vs->vd->auth); 20348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_flush(vs); 20355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner start_client_init(vs); 20365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (vs->vd->auth == VNC_AUTH_VNC) { 20378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VNC_DEBUG("Tell client VNC auth\n"); 20385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u32(vs, vs->vd->auth); 20398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_flush(vs); 20408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project start_auth_vnc(vs); 20418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 20425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->vd->auth); 20438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write_u32(vs, VNC_AUTH_INVALID); 20448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_flush(vs); 20458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_client_error(vs); 20468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 20478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 20485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Telling client we support auth %d\n", vs->vd->auth); 20495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, 1); /* num auth */ 20505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_write_u8(vs, vs->vd->auth); 20515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_read_when(vs, protocol_client_auth, 1); 20525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_flush(vs); 20538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 20548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 20558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 20568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 20578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 20585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vnc_connect(VncDisplay *vd, int csock) 20598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 20605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncState *vs = qemu_mallocz(sizeof(VncState)); 20615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->csock = csock; 20625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("New client on socket %d\n", csock); 20645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dcl->idle = 0; 20658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project socket_set_nonblock(vs->csock); 20668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs); 20675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->vd = vd; 20695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->ds = vd->ds; 20705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs); 20715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->last_x = -1; 20725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->last_y = -1; 20735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->as.freq = 44100; 20755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->as.nchannels = 2; 20765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->as.fmt = AUD_FMT_S16; 20775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->as.endianness = 0; 20785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_resize(vs); 20808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_write(vs, "RFB 003.008\n", 12); 20818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_flush(vs); 20828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_read_when(vs, protocol_version, 12); 20835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner reset_keys(vs); 20845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->next = vd->clients; 20865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vd->clients = vs; 20875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_update_client(vs); 20895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* vs might be free()ed here */ 20908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 20918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 20928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void vnc_listen_read(void *opaque) 20938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 20945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncDisplay *vs = opaque; 20955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in addr; 20965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socklen_t addrlen = sizeof(addr); 20978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 20988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Catch-up */ 20998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vga_hw_update(); 21008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen); 21025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (csock != -1) { 21035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_connect(vs, csock); 21048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 21058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 21068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid vnc_display_init(DisplayState *ds) 21088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 21095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncDisplay *vs = qemu_mallocz(sizeof(*vs)); 21108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dcl = qemu_mallocz(sizeof(DisplayChangeListener)); 21128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ds->opaque = vs; 21145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dcl->idle = 1; 21155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_display = vs; 21168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->lsock = -1; 21188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->ds = ds; 21208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (keyboard_layout) 21225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout); 21238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 21245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->kbd_layout = init_keyboard_layout(name2keysym, "en-us"); 21258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!vs->kbd_layout) 21275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner exit(1); 21288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dcl->dpy_copy = vnc_dpy_copy; 21305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dcl->dpy_update = vnc_dpy_update; 21315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dcl->dpy_resize = vnc_dpy_resize; 21325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dcl->dpy_setdata = vnc_dpy_setdata; 21335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner register_displaychangelistener(ds, dcl); 21348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 21358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid vnc_display_close(DisplayState *ds) 21388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 21395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; 21408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!vs) 21425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 21438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (vs->display) { 21445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(vs->display); 21455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->display = NULL; 21468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 21478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (vs->lsock != -1) { 21485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL); 21495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(vs->lsock); 21505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->lsock = -1; 21518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 21528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->auth = VNC_AUTH_INVALID; 21538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_VNC_TLS 21548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vs->subauth = VNC_AUTH_INVALID; 21555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->tls.x509verify = 0; 21568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 21578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 21588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint vnc_display_password(DisplayState *ds, const char *password) 21608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 21615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; 21628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (vs->password) { 21645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(vs->password); 21655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->password = NULL; 21668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 21678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (password && password[0]) { 21685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!(vs->password = qemu_strdup(password))) 21695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 21708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 21718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 21738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 21748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerchar *vnc_display_local_addr(DisplayState *ds) 21765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 21775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; 21785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 21795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return vnc_socket_local_addr("%s:%s", vs->lsock); 21805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 21815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 21828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint vnc_display_open(DisplayState *ds, const char *display) 21838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 21845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; 21858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const char *options; 21868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int password = 0; 21878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int reverse = 0; 21885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int to_port = 0; 21898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_VNC_TLS 21908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int tls = 0, x509 = 0; 21918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 21925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VNC_SASL 21935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int sasl = 0; 21945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int saslErr; 21955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 21965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int acl = 0; 21978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 21985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!vnc_display) 21995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 22008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project vnc_display_close(ds); 22018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (strcmp(display, "none") == 0) 22025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 22038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 22048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(vs->display = strdup(display))) 22055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 22068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 22078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project options = display; 22088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while ((options = strchr(options, ','))) { 22095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner options++; 22105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strncmp(options, "password", 8) == 0) { 22115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner password = 1; /* Require password auth */ 22125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (strncmp(options, "reverse", 7) == 0) { 22135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner reverse = 1; 22145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (strncmp(options, "to=", 3) == 0) { 22155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner to_port = atoi(options+3) + 5900; 22165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VNC_SASL 22175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (strncmp(options, "sasl", 4) == 0) { 22185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sasl = 1; /* Require SASL auth */ 22195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 22208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_VNC_TLS 22215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (strncmp(options, "tls", 3) == 0) { 22225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tls = 1; /* Require TLS */ 22235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (strncmp(options, "x509", 4) == 0) { 22245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *start, *end; 22255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner x509 = 1; /* Require x509 certificates */ 22265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strncmp(options, "x509verify", 10) == 0) 22275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->tls.x509verify = 1; /* ...and verify client certs */ 22285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 22295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Now check for 'x509=/some/path' postfix 22305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * and use that to setup x509 certificate/key paths */ 22315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner start = strchr(options, '='); 22325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner end = strchr(options, ','); 22335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (start && (!end || (start < end))) { 22345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int len = end ? end-(start+1) : strlen(start+1); 22355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *path = qemu_strndup(start + 1, len); 22365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 22375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Trying certificate path '%s'\n", path); 22385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vnc_tls_set_x509_creds_dir(vs, path) < 0) { 22395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed to find x509 certificates/keys in %s\n", path); 22405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(path); 22415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(vs->display); 22425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->display = NULL; 22435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 22445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project qemu_free(path); 22465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 22475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "No certificate path provided\n"); 22485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(vs->display); 22495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->display = NULL; 22505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 22515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 22535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (strncmp(options, "acl", 3) == 0) { 22545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner acl = 1; 22555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 22578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 22588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_VNC_TLS 22595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (acl && x509 && vs->tls.x509verify) { 22605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!(vs->tls.acl = qemu_acl_init("vnc.x509dname"))) { 22615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed to create x509 dname ACL\n"); 22625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner exit(1); 22635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 22665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VNC_SASL 22675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (acl && sasl) { 22685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!(vs->sasl.acl = qemu_acl_init("vnc.username"))) { 22695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed to create username ACL\n"); 22705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner exit(1); 22715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 22745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 22755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 22765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Combinations we support here: 22775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 22785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * - no-auth (clear text, no auth) 22795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * - password (clear text, weak auth) 22805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * - sasl (encrypt, good auth *IF* using Kerberos via GSSAPI) 22815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * - tls (encrypt, weak anonymous creds, no auth) 22825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * - tls + password (encrypt, weak anonymous creds, weak auth) 22835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * - tls + sasl (encrypt, weak anonymous creds, good auth) 22845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * - tls + x509 (encrypt, good x509 creds, no auth) 22855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * - tls + x509 + password (encrypt, good x509 creds, weak auth) 22865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * - tls + x509 + sasl (encrypt, good x509 creds, good auth) 22875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 22885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * NB1. TLS is a stackable auth scheme. 22895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * NB2. the x509 schemes have option to validate a client cert dname 22905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 22915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (password) { 22925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VNC_TLS 22935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tls) { 22945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->auth = VNC_AUTH_VENCRYPT; 22955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (x509) { 22965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Initializing VNC server with x509 password auth\n"); 22975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->subauth = VNC_AUTH_VENCRYPT_X509VNC; 22985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 22995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Initializing VNC server with TLS password auth\n"); 23005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC; 23015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 23035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* CONFIG_VNC_TLS */ 23045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Initializing VNC server with password auth\n"); 23055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->auth = VNC_AUTH_VNC; 23065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VNC_TLS 23075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->subauth = VNC_AUTH_INVALID; 23085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* CONFIG_VNC_TLS */ 23105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VNC_SASL 23115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (sasl) { 23125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VNC_TLS 23135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tls) { 23145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->auth = VNC_AUTH_VENCRYPT; 23155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (x509) { 23165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Initializing VNC server with x509 SASL auth\n"); 23175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->subauth = VNC_AUTH_VENCRYPT_X509SASL; 23185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 23195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Initializing VNC server with TLS SASL auth\n"); 23205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->subauth = VNC_AUTH_VENCRYPT_TLSSASL; 23215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 23235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* CONFIG_VNC_TLS */ 23245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Initializing VNC server with SASL auth\n"); 23255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->auth = VNC_AUTH_SASL; 23265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VNC_TLS 23275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->subauth = VNC_AUTH_INVALID; 23285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* CONFIG_VNC_TLS */ 23305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* CONFIG_VNC_SASL */ 23318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 23328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_VNC_TLS 23335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tls) { 23345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->auth = VNC_AUTH_VENCRYPT; 23355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (x509) { 23365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Initializing VNC server with x509 no auth\n"); 23375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->subauth = VNC_AUTH_VENCRYPT_X509NONE; 23385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 23395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Initializing VNC server with TLS no auth\n"); 23405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE; 23415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 23438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 23445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VNC_DEBUG("Initializing VNC server with no auth\n"); 23455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->auth = VNC_AUTH_NONE; 23468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_VNC_TLS 23475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->subauth = VNC_AUTH_INVALID; 23485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 23508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 23515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 23525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VNC_SASL 23535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((saslErr = sasl_server_init(NULL, "qemu")) != SASL_OK) { 23545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed to initialize SASL auth %s", 23555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sasl_errstring(saslErr, NULL, NULL)); 23565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(vs->display); 23575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->display = NULL; 23585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 23598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 23605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 23618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 23628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (reverse) { 23635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* connect to viewer */ 23645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strncmp(display, "unix:", 5) == 0) 23655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->lsock = unix_connect(display+5); 23665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 23675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->lsock = inet_connect(display, SOCK_STREAM); 23685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (-1 == vs->lsock) { 23695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(vs->display); 23705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->display = NULL; 23715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 23725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 23735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int csock = vs->lsock; 23745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->lsock = -1; 23755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vnc_connect(vs, csock); 23768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 23778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 23788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 23795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 23805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* listen for connects */ 23815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *dpy; 23825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dpy = qemu_malloc(256); 23835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strncmp(display, "unix:", 5) == 0) { 23845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pstrcpy(dpy, 256, "unix:"); 23855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->lsock = unix_listen(display+5, dpy+5, 256-5); 23865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 23875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->lsock = inet_listen(display, dpy, 256, SOCK_STREAM, 5900); 23885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (-1 == vs->lsock) { 23905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(dpy); 23915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 23925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 23935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(vs->display); 23945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vs->display = dpy; 23955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 23975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return qemu_set_fd_handler2(vs->lsock, NULL, vnc_listen_read, NULL, vs); 23988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2399